pi-harness-workspace 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +152 -0
  2. package/apps/web/dist/assets/index-C4tLweAB.js +20 -0
  3. package/apps/web/dist/assets/index-DPgRbQ4_.css +1 -0
  4. package/apps/web/dist/index.html +14 -0
  5. package/apps/web/index.html +13 -0
  6. package/apps/web/package.json +24 -0
  7. package/apps/web/profile/cordis.yml +44 -0
  8. package/apps/web/server-dist/bin.d.ts +3 -0
  9. package/apps/web/server-dist/bin.d.ts.map +1 -0
  10. package/apps/web/server-dist/bin.js +67 -0
  11. package/apps/web/server-dist/bin.js.map +1 -0
  12. package/apps/web/src/command-palette.ts +84 -0
  13. package/apps/web/src/file-diff.ts +42 -0
  14. package/apps/web/src/main.ts +12 -0
  15. package/apps/web/src/runtime.css +4 -0
  16. package/apps/web/src/server/bin.ts +64 -0
  17. package/apps/web/src/style.css +7 -0
  18. package/apps/web/tsconfig.build.json +1 -0
  19. package/apps/web/tsconfig.json +1 -0
  20. package/package.json +41 -0
  21. package/packages/api-gateway/dist/index.d.ts +8 -0
  22. package/packages/api-gateway/dist/index.d.ts.map +1 -0
  23. package/packages/api-gateway/dist/index.js +582 -0
  24. package/packages/api-gateway/dist/index.js.map +1 -0
  25. package/packages/api-gateway/package.json +22 -0
  26. package/packages/api-gateway/src/index.ts +577 -0
  27. package/packages/api-gateway/test/index.test.ts +327 -0
  28. package/packages/api-gateway/tsconfig.build.json +1 -0
  29. package/packages/api-gateway/tsconfig.json +1 -0
  30. package/packages/bundle-web-app/cordis.patch.yml +12 -0
  31. package/packages/bundle-web-app/dist/index.d.ts +12 -0
  32. package/packages/bundle-web-app/dist/index.d.ts.map +1 -0
  33. package/packages/bundle-web-app/dist/index.js +63 -0
  34. package/packages/bundle-web-app/dist/index.js.map +1 -0
  35. package/packages/bundle-web-app/package.json +22 -0
  36. package/packages/bundle-web-app/src/index.ts +69 -0
  37. package/packages/bundle-web-app/test/index.test.ts +29 -0
  38. package/packages/bundle-web-app/tsconfig.build.json +1 -0
  39. package/packages/bundle-web-app/tsconfig.json +1 -0
  40. package/packages/cli/dist/args.d.ts +16 -0
  41. package/packages/cli/dist/args.d.ts.map +1 -0
  42. package/packages/cli/dist/args.js +53 -0
  43. package/packages/cli/dist/args.js.map +1 -0
  44. package/packages/cli/dist/bin.d.ts +3 -0
  45. package/packages/cli/dist/bin.d.ts.map +1 -0
  46. package/packages/cli/dist/bin.js +40 -0
  47. package/packages/cli/dist/bin.js.map +1 -0
  48. package/packages/cli/dist/main.d.ts +14 -0
  49. package/packages/cli/dist/main.d.ts.map +1 -0
  50. package/packages/cli/dist/main.js +148 -0
  51. package/packages/cli/dist/main.js.map +1 -0
  52. package/packages/cli/dist/node-stdio.d.ts +10 -0
  53. package/packages/cli/dist/node-stdio.d.ts.map +1 -0
  54. package/packages/cli/dist/node-stdio.js +34 -0
  55. package/packages/cli/dist/node-stdio.js.map +1 -0
  56. package/packages/cli/dist/relaunch.d.ts +5 -0
  57. package/packages/cli/dist/relaunch.d.ts.map +1 -0
  58. package/packages/cli/dist/relaunch.js +52 -0
  59. package/packages/cli/dist/relaunch.js.map +1 -0
  60. package/packages/cli/package.json +25 -0
  61. package/packages/cli/src/args.ts +50 -0
  62. package/packages/cli/src/bin.ts +41 -0
  63. package/packages/cli/src/main.ts +155 -0
  64. package/packages/cli/src/node-stdio.ts +40 -0
  65. package/packages/cli/src/relaunch.ts +48 -0
  66. package/packages/cli/test/args.test.ts +28 -0
  67. package/packages/cli/test/cli.test.ts +153 -0
  68. package/packages/cli/test/relaunch.test.ts +29 -0
  69. package/packages/cli/tsconfig.build.json +11 -0
  70. package/packages/cli/tsconfig.json +10 -0
  71. package/packages/client-web/dist/control-room.d.ts +102 -0
  72. package/packages/client-web/dist/control-room.d.ts.map +1 -0
  73. package/packages/client-web/dist/control-room.js +12 -0
  74. package/packages/client-web/dist/control-room.js.map +1 -0
  75. package/packages/client-web/dist/design-contract.d.ts +85 -0
  76. package/packages/client-web/dist/design-contract.d.ts.map +1 -0
  77. package/packages/client-web/dist/design-contract.js +99 -0
  78. package/packages/client-web/dist/design-contract.js.map +1 -0
  79. package/packages/client-web/dist/index.d.ts +17 -0
  80. package/packages/client-web/dist/index.d.ts.map +1 -0
  81. package/packages/client-web/dist/index.js +19 -0
  82. package/packages/client-web/dist/index.js.map +1 -0
  83. package/packages/client-web/dist/react-room.d.ts +6 -0
  84. package/packages/client-web/dist/react-room.d.ts.map +1 -0
  85. package/packages/client-web/dist/react-room.js +103 -0
  86. package/packages/client-web/dist/react-room.js.map +1 -0
  87. package/packages/client-web/package.json +29 -0
  88. package/packages/client-web/src/control-room.ts +10 -0
  89. package/packages/client-web/src/design-contract.ts +112 -0
  90. package/packages/client-web/src/index.ts +21 -0
  91. package/packages/client-web/src/react-room.tsx +78 -0
  92. package/packages/client-web/test/design-contract.test.ts +24 -0
  93. package/packages/client-web/tsconfig.build.json +1 -0
  94. package/packages/client-web/tsconfig.json +1 -0
  95. package/packages/core/dist/boot.d.ts +13 -0
  96. package/packages/core/dist/boot.d.ts.map +1 -0
  97. package/packages/core/dist/boot.js +96 -0
  98. package/packages/core/dist/boot.js.map +1 -0
  99. package/packages/core/dist/context.d.ts +3 -0
  100. package/packages/core/dist/context.d.ts.map +1 -0
  101. package/packages/core/dist/context.js +2 -0
  102. package/packages/core/dist/context.js.map +1 -0
  103. package/packages/core/dist/index.d.ts +7 -0
  104. package/packages/core/dist/index.d.ts.map +1 -0
  105. package/packages/core/dist/index.js +6 -0
  106. package/packages/core/dist/index.js.map +1 -0
  107. package/packages/core/dist/plugins/model.d.ts +8 -0
  108. package/packages/core/dist/plugins/model.d.ts.map +1 -0
  109. package/packages/core/dist/plugins/model.js +12 -0
  110. package/packages/core/dist/plugins/model.js.map +1 -0
  111. package/packages/core/dist/plugins/models.d.ts +16 -0
  112. package/packages/core/dist/plugins/models.d.ts.map +1 -0
  113. package/packages/core/dist/plugins/models.js +24 -0
  114. package/packages/core/dist/plugins/models.js.map +1 -0
  115. package/packages/core/dist/plugins/resources.d.ts +18 -0
  116. package/packages/core/dist/plugins/resources.d.ts.map +1 -0
  117. package/packages/core/dist/plugins/resources.js +48 -0
  118. package/packages/core/dist/plugins/resources.js.map +1 -0
  119. package/packages/core/dist/plugins/runtime.d.ts +14 -0
  120. package/packages/core/dist/plugins/runtime.d.ts.map +1 -0
  121. package/packages/core/dist/plugins/runtime.js +68 -0
  122. package/packages/core/dist/plugins/runtime.js.map +1 -0
  123. package/packages/core/dist/plugins/session.d.ts +15 -0
  124. package/packages/core/dist/plugins/session.d.ts.map +1 -0
  125. package/packages/core/dist/plugins/session.js +20 -0
  126. package/packages/core/dist/plugins/session.js.map +1 -0
  127. package/packages/core/dist/plugins/stdio.d.ts +8 -0
  128. package/packages/core/dist/plugins/stdio.d.ts.map +1 -0
  129. package/packages/core/dist/plugins/stdio.js +20 -0
  130. package/packages/core/dist/plugins/stdio.js.map +1 -0
  131. package/packages/core/dist/plugins/tools.d.ts +13 -0
  132. package/packages/core/dist/plugins/tools.d.ts.map +1 -0
  133. package/packages/core/dist/plugins/tools.js +17 -0
  134. package/packages/core/dist/plugins/tools.js.map +1 -0
  135. package/packages/core/dist/profile.d.ts +8 -0
  136. package/packages/core/dist/profile.d.ts.map +1 -0
  137. package/packages/core/dist/profile.js +28 -0
  138. package/packages/core/dist/profile.js.map +1 -0
  139. package/packages/core/dist/runtime.d.ts +16 -0
  140. package/packages/core/dist/runtime.d.ts.map +1 -0
  141. package/packages/core/dist/runtime.js +33 -0
  142. package/packages/core/dist/runtime.js.map +1 -0
  143. package/packages/core/dist/services.d.ts +63 -0
  144. package/packages/core/dist/services.d.ts.map +1 -0
  145. package/packages/core/dist/services.js +39 -0
  146. package/packages/core/dist/services.js.map +1 -0
  147. package/packages/core/dist/stdio.d.ts +25 -0
  148. package/packages/core/dist/stdio.d.ts.map +1 -0
  149. package/packages/core/dist/stdio.js +74 -0
  150. package/packages/core/dist/stdio.js.map +1 -0
  151. package/packages/core/package.json +44 -0
  152. package/packages/core/profiles/default/cordis.yml +35 -0
  153. package/packages/core/profiles/development/cordis.yml +47 -0
  154. package/packages/core/src/boot.ts +103 -0
  155. package/packages/core/src/context.ts +3 -0
  156. package/packages/core/src/index.ts +6 -0
  157. package/packages/core/src/plugins/model.ts +12 -0
  158. package/packages/core/src/plugins/models.ts +32 -0
  159. package/packages/core/src/plugins/resources.ts +57 -0
  160. package/packages/core/src/plugins/runtime.ts +73 -0
  161. package/packages/core/src/plugins/session.ts +27 -0
  162. package/packages/core/src/plugins/stdio.ts +20 -0
  163. package/packages/core/src/plugins/tools.ts +23 -0
  164. package/packages/core/src/profile.ts +31 -0
  165. package/packages/core/src/runtime.ts +39 -0
  166. package/packages/core/src/services.ts +105 -0
  167. package/packages/core/src/stdio.ts +88 -0
  168. package/packages/core/test/boot.test.ts +86 -0
  169. package/packages/core/test/profile.test.ts +39 -0
  170. package/packages/core/test/profiles.integration.test.ts +93 -0
  171. package/packages/core/test/runtime-fixture.ts +31 -0
  172. package/packages/core/test/runtime.test.ts +54 -0
  173. package/packages/core/test/services.test.ts +131 -0
  174. package/packages/core/test/stdio.test.ts +87 -0
  175. package/packages/core/tsconfig.build.json +10 -0
  176. package/packages/core/tsconfig.json +10 -0
  177. package/packages/host-webserver/dist/index.d.ts +29 -0
  178. package/packages/host-webserver/dist/index.d.ts.map +1 -0
  179. package/packages/host-webserver/dist/index.js +73 -0
  180. package/packages/host-webserver/dist/index.js.map +1 -0
  181. package/packages/host-webserver/package.json +18 -0
  182. package/packages/host-webserver/src/index.ts +97 -0
  183. package/packages/host-webserver/test/index.test.ts +43 -0
  184. package/packages/host-webserver/tsconfig.build.json +1 -0
  185. package/packages/host-webserver/tsconfig.json +1 -0
@@ -0,0 +1 @@
1
+ :root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--ink:#0f1115;--muted:#81858c;--faint:#adb2b8;--line:#00000017;--soft:#f9fafb;--blue:#4176e6;--blue-soft:#edf3fe;--green:#22c55e;--red:#ec1313;--amber:#f59e0b;--mono:"JetBrains Mono","SFMono-Regular",Consolas,monospace;--sans:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif}*{box-sizing:border-box}html,body,#root{width:100%;height:100%;margin:0;overflow:hidden}body{color:var(--ink);font:13px/1.5 var(--sans);-webkit-font-smoothing:antialiased;background:#fff}button,input,textarea,select{font:inherit;color:inherit}button{cursor:pointer;background:0 0;border:0}button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline-offset:1px;outline:2px solid #4176e673}[hidden]{display:none!important}.app-frame{background:#fff;width:100%;height:100%;display:flex;overflow:hidden}.sidebar{background:var(--soft);border-right:1px solid #0000000f;flex-direction:column;flex:0 0 264px;width:264px;min-height:0;display:flex}.brand-row{flex:0 0 48px;align-items:center;gap:9px;height:48px;padding:0 14px;display:flex}.brand-row strong{letter-spacing:-.1px;font-size:13px;font-weight:600}.pi-mark{background:var(--ink);color:#fff;width:22px;height:22px;font:13px var(--mono);border-radius:6px;flex:none;place-items:center;display:grid}.pi-mark.large{border-radius:11px;width:38px;height:38px;font-size:19px}.version{color:var(--faint);font:10px var(--mono);margin-left:auto}.sidebar-actions{flex-direction:column;gap:8px;padding:0 10px 10px;display:flex}.new-session{background:var(--ink);color:#fff;border-radius:8px;justify-content:center;align-items:center;gap:6px;height:32px;font-size:12.5px;font-weight:500;display:flex}.new-session:hover,.send-button:hover{background:#43454a}.sidebar-actions input{background:#fff;border:1px solid #0000001a;border-radius:8px;outline:none;width:100%;height:30px;padding:0 10px;font-size:12px}.sidebar-scroll{flex:1;min-height:0;padding:0 8px 8px;overflow:auto}.session-group{margin-bottom:8px}.group-label{color:var(--faint);letter-spacing:.04em;padding:6px 8px 4px;font-size:10px}.session-row{text-align:left;border-radius:8px;align-items:center;gap:7px;width:100%;padding:7px 9px;display:flex}.session-row:hover{background:#f1f3f5}.session-row.active{background:#ebeef2}.session-dot{background:#cfd3d6;border-radius:50%;flex:none;width:6px;height:6px}.session-dot.running{background:var(--green);animation:1.4s ease-in-out infinite pulse}.session-dot.ok{background:var(--green)}.session-dot.warn{background:var(--amber)}.session-dot.error{background:var(--red)}.session-copy{flex-direction:column;gap:2px;min-width:0;display:flex}.session-copy strong{text-overflow:ellipsis;white-space:nowrap;font-size:12.5px;font-weight:600;overflow:hidden}.session-copy small{text-overflow:ellipsis;white-space:nowrap;color:var(--faint);font:10px var(--mono);overflow:hidden}.runtime-cells{color:var(--faint);font:9.5px var(--mono);border-top:1px solid #0000000f;flex-wrap:wrap;gap:4px 12px;padding:8px 19px 9px;display:flex}.runtime-cells span{gap:5px;display:flex}.runtime-cells b{font-weight:400}.runtime-cells strong{color:#61666b;font-weight:400}.sidebar-footer{border-top:1px solid #0000000f;flex-direction:column;gap:2px;padding:6px 10px 8px;display:flex}.sidebar-link{text-align:left;border-radius:8px;align-items:center;gap:9px;height:30px;padding:0 9px;font-size:12.5px;display:flex}.sidebar-link:hover{background:#f1f3f5}.sidebar-link span:nth-child(2){flex:1}.sidebar-link b{color:#61666b;font:10px var(--mono);background:#ebeef2;border-radius:20px;padding:1px 6px;font-weight:400}.link-glyph{color:var(--blue);font:11.5px var(--mono)}.main-pane{flex-direction:column;flex:1;min-width:0;display:flex}.main-header{border-bottom:1px solid #0000000f;flex:0 0 48px;align-items:center;gap:12px;height:48px;padding:0 16px;display:flex}.active-heading{flex-direction:column;min-width:0;display:flex}.active-heading strong,.active-heading small{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.active-heading strong{font-size:13px;font-weight:600}.active-heading small{color:var(--faint);font:10px var(--mono)}.header-spacer{flex:1}.run-indicator{color:#61666b;font:10.5px var(--mono);flex:none;align-items:center;gap:6px;display:flex}.run-indicator>span{background:var(--green);border-radius:50%;width:6px;height:6px;animation:1.4s ease-in-out infinite pulse}.run-indicator button{color:var(--red);border:1px solid #ec13133d;border-radius:6px;padding:2px 8px;font-size:11px}.run-indicator.running>span{background:var(--blue)}.view-tabs{background:#f1f3f5;border-radius:8px;gap:2px;padding:2px;display:flex}.view-tab{color:var(--muted);border-radius:6px;padding:4px 11px;font-size:12px}.view-tab.active{color:var(--ink);background:#fff;font-weight:600;box-shadow:0 1px 3px #00000014}.session-menu,.details-toggle{color:#61666b;background:#fff;border:1px solid #0000001a;border-radius:8px;height:28px}.session-menu{width:28px;font-size:15px}.details-toggle{padding:0 9px;font-size:12px}.session-menu:hover,.details-toggle:hover{background:#f1f3f5}.view-host,.view-panel{flex-direction:column;flex:1;min-height:0;display:flex}.chat-scroll{flex:1;min-height:0;padding:20px 24px 4px;overflow-y:auto}.turn{max-width:748px;margin:0 auto 16px;font-size:13.5px;line-height:1.78}.turn.user{justify-content:flex-end;display:flex}.user-bubble{background:var(--blue-soft);white-space:pre-wrap;border-radius:12px;max-width:84%;padding:10px 14px}.turn-text{white-space:pre-wrap;margin:0}.reasoning-head{color:var(--muted);align-items:center;gap:6px;padding:0;font-size:11.5px;display:flex}.reasoning-head .caret{color:var(--faint);font-size:9px}.reasoning-body{color:#61666b;white-space:pre-wrap;border-left:2px solid #ebeef2;margin:6px 0 0;padding-left:11px;font-size:12.5px;line-height:1.75;display:none}.reasoning:hover .reasoning-body{display:block}.plugin-event{height:30px;color:var(--blue);font:11px var(--mono);background:#f7faff;border:1px dashed #4176e659;border-radius:8px;align-items:center;gap:8px;padding:0 11px;display:flex}.plugin-event>span:last-child{text-overflow:ellipsis;white-space:nowrap;color:#61666b;font:12px var(--sans);overflow:hidden}.plugin-hook{background:#e4edfd;border-radius:4px;padding:1px 6px;color:#81858c!important;font:10px var(--mono)!important}.tool-card,.approval-card,.subagent-card,.todo-card{border:1px solid var(--line);background:#fff;border-radius:10px;overflow:hidden}.tool-head,.subagent-head{text-align:left;background:#fff;align-items:center;gap:9px;width:100%;min-height:34px;padding:7px 11px;display:flex}.tool-head{font:11.5px var(--mono)}.tool-glyph{width:12px;color:var(--muted)}.tool-target,.subagent-goal{text-overflow:ellipsis;white-space:nowrap;color:var(--muted);font-size:11px;overflow:hidden}.tool-head .tool-target,.subagent-goal{flex:1}.tool-stat{color:var(--muted)}.tool-detail-link{color:var(--blue);font:10.5px var(--sans)}.tool-output,.diff-preview,.toml{background:var(--soft);white-space:pre-wrap;word-break:break-word;color:#61666b;font:11.5px/1.7 var(--mono);border-top:1px solid #0000000f;margin:0;padding:10px 12px}.diff-line{font:11.5px/1.7 var(--mono);gap:10px;padding:0 8px;display:flex}.diff-line.added{background:#e6faed}.diff-line.removed{background:#fff0f0}.diff-no{width:30px;color:var(--faint);text-align:right}.diff-sign{width:8px;color:var(--green)}.diff-line.removed .diff-sign{color:var(--red)}.approval-card{background:#fffaf0;border-color:#f59e0b66;padding:11px 13px}.approval-card pre{background:0 0;border:0;padding:8px 0}.approval-actions{gap:7px;margin-top:4px;display:flex}.approval-actions button,.plugin-add button{border:1px solid var(--line);background:#fff;border-radius:7px;padding:5px 11px;font-size:11.5px}.approval-actions .primary,.plugin-add .primary{background:var(--ink);color:#fff}.approval-actions .danger{color:var(--red)}.subagent-head{font-size:12.5px}.subagent-glyph{color:#679efe;font:11px var(--mono)}.subagent-preset{color:#81858c;font:10.5px var(--mono);background:#e4edfd;border-radius:4px;padding:1px 6px}.subagent-duration{color:var(--faint);font:10.5px var(--mono)}.subagent-body{border-top:1px solid #0000000f;padding:4px 11px 9px;display:block}.subagent-lineage{color:var(--faint);font:10px var(--mono);padding:6px 0 4px;display:block}.subagent-step{border-left:2px solid #e4edfd;align-items:center;gap:8px;padding:4px 0 4px 10px;display:flex}.subagent-step code{width:42px;color:var(--muted);font:10.5px var(--mono)}.subagent-step span{text-overflow:ellipsis;white-space:nowrap;color:#61666b;font:11px var(--mono);flex:1;overflow:hidden}.subagent-step small{color:var(--faint);font:10px var(--mono)}.subagent-body p{border-top:1px solid #0000000f;margin:8px 0 0;padding-top:8px}.todo-head{border-bottom:1px solid #0000000f;align-items:center;gap:8px;height:32px;padding:0 11px;display:flex}.todo-head small{color:var(--faint);font:10.5px var(--mono)}.todo-row{border-bottom:1px solid #0000000a;align-items:flex-start;gap:9px;padding:7px 11px;display:flex}.todo-row.done{color:var(--muted);text-decoration:line-through}.todo-mark{color:var(--green);font:11px var(--mono)}.stats-row{color:var(--faint);font:10.5px var(--mono);flex-wrap:wrap;gap:14px;display:flex}.composer-wrap{flex:none;padding:8px 24px 14px}.context-line{max-width:748px;color:var(--faint);font:10.5px var(--mono);align-items:center;gap:9px;margin:0 auto 8px;display:flex}.context-line b{color:var(--muted);font-weight:400}.context-line button{color:var(--blue);padding:0;font-size:11px}.context-bar{background:#ebeef2;border-radius:3px;flex:1;height:4px;display:flex;overflow:hidden}.context-bar i{height:100%}.context-bar.expanded{height:8px}.composer{background:#fff;border:1px solid #0000001f;border-radius:12px;max-width:748px;margin:0 auto;overflow:hidden;box-shadow:0 1px 2px #00000008}.composer textarea{resize:none;width:100%;min-height:65px;color:var(--ink);background:0 0;border:0;outline:0;padding:11px 13px 4px;font-size:13.5px;line-height:1.7;display:block}.composer-tools{align-items:center;gap:6px;padding:6px 8px 8px;display:flex}.composer-tools select,.tool-chip{height:26px;font:11px var(--mono);background:#fff;border:1px solid #0000001a;border-radius:7px;padding:0 7px}.tool-chip{color:#61666b;font-family:var(--sans);padding:0 9px;font-size:11.5px}.composer-hint{color:#cfd3d6;font:10px var(--mono);text-align:right;flex:1}.send-button{background:var(--ink);color:#fff;border-radius:8px;width:28px;height:28px;font-size:15px}.send-button:disabled{cursor:not-allowed;opacity:.45}.new-session-screen{text-align:center;flex-direction:column;align-items:center;gap:11px;max-width:580px;margin:0 auto;padding:40px 0;display:flex}.new-session-screen h2{margin:0;font-size:16.5px}.new-session-screen p{color:var(--muted);margin:0}.workspace-picker{text-align:left;gap:6px;width:100%;margin-top:12px;display:grid}.workspace-row{border:1px solid var(--line);text-align:left;background:#fff;border-radius:9px;align-items:center;gap:10px;width:100%;padding:10px 12px;display:flex}.workspace-row:hover{background:var(--soft);border-color:#4176e666}.workspace-row code{text-overflow:ellipsis;white-space:nowrap;font:12px var(--mono);flex:1;overflow:hidden}.workspace-row small{color:var(--faint);font:10px var(--mono);margin-top:3px;display:block}.workspace-row .live{color:var(--green)}.workspace-row .offline{color:#cfd3d6}.effective-config{background:var(--soft);text-align:left;border:1px solid #00000014;border-radius:10px;flex-wrap:wrap;align-items:center;gap:10px;width:100%;padding:9px 12px;display:flex}.effective-config code{color:var(--faint);font:10.5px var(--mono)}.effective-config span{color:#61666b;font:10.5px var(--mono)}.trajectory-summary{border-bottom:1px solid var(--line);color:var(--muted);flex:none;padding:12px 16px 10px;font-size:11.5px}.trajectory-summary b{color:var(--faint);font:10.5px var(--mono);margin-left:9px;font-weight:400}.timeline{gap:3px;height:26px;margin-top:8px;display:flex}.timeline-turn{background:#ebeef2;border-radius:3px;align-items:stretch;padding:0;display:flex;overflow:hidden}.timeline-strip{opacity:.9;width:100%;display:block}.source-filters{border-bottom:1px solid var(--line);flex-wrap:wrap;flex:none;align-items:center;gap:6px;padding:9px 16px;display:flex}.filter{color:var(--muted);border:1px solid #0000001a;border-radius:20px;align-items:center;gap:6px;padding:3px 9px;font-size:11.5px;display:flex}.filter.active{background:var(--blue-soft);color:var(--blue);border-color:#4176e659}.filter b{color:var(--faint);font:10px var(--mono);font-weight:400}.event-count{color:var(--faint);font:10.5px var(--mono);margin-left:auto}.event-table{flex:1;min-height:0;overflow:auto}.event-head,.event-row{grid-template-columns:78px 132px 1fr 88px 68px;align-items:center;gap:12px;padding:7px 16px;display:grid}.event-head{background:var(--soft);color:var(--faint);font:10px var(--mono);letter-spacing:.04em;text-transform:uppercase;border-bottom:1px solid #0000000f}.event-row{text-align:left;border-bottom:1px solid #0000000a;width:100%;font-size:12px}.event-row:hover{background:var(--soft)}.event-row>span,.event-row code{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.event-row>span:first-child,.event-row>span:last-child{color:var(--faint);font:10.5px var(--mono)}.event-row strong{text-overflow:ellipsis;white-space:nowrap;font-weight:400;overflow:hidden}.event-row>span:nth-child(2){color:#61666b;font:11px var(--mono);align-items:center;gap:7px;display:flex}.event-dot{background:var(--blue);border-radius:2px;flex:none;width:6px;height:6px}.files-content{max-width:820px;padding:18px 24px}.files-title{align-items:baseline;gap:10px;margin-bottom:14px;display:flex}.files-title strong{font-size:13px}.files-title span{color:var(--faint);font:11px var(--mono)}.file-list{border:1px solid var(--line);border-radius:10px;overflow:hidden}.file-row{border-bottom:1px solid #0000000a;align-items:center;gap:12px;padding:10px 13px;display:flex}.file-row:last-child{border-bottom:0}.file-row code{text-overflow:ellipsis;white-space:nowrap;font:12px var(--mono);flex:1;overflow:hidden}.file-kind{color:#61666b;font:10px var(--mono);background:#f1f3f5;border-radius:4px;padding:1px 6px}.file-kind.new{color:#16a34a;background:#e6faed}.file-row .add{color:var(--green);font:11px var(--mono)}.file-row .del{color:var(--red);font:11px var(--mono)}.diff-button{color:var(--blue);font-size:11.5px}.file-actions{gap:8px;margin-top:12px;display:flex}.file-actions button{border:1px solid var(--line);background:#fff;border-radius:7px;padding:6px 11px;font-size:11.5px}.file-actions .primary{background:var(--ink);color:#fff}.details-panel{background:#fff;border-left:1px solid #0000001a;flex:0 336px;width:336px;min-width:268px}.details-panel>header{border-bottom:1px solid #0000000f;align-items:center;gap:8px;height:40px;padding:0 12px;display:flex}.details-panel>header strong{flex:1;font-size:13px}.details-panel>header button{color:var(--muted);font-size:19px;line-height:1}.details-body{padding:12px;overflow:auto}.detail-stats{grid-template-columns:1fr 1fr;gap:7px;margin-bottom:12px;display:grid}.detail-stats>div{border:1px solid #00000014;border-radius:8px;padding:9px}.detail-stats small,.detail-section>small{color:var(--faint);font:9.5px var(--mono);letter-spacing:.04em;display:block}.detail-stats b{font:12.5px var(--mono);margin-top:2px;font-weight:400;display:block}.detail-section{flex-direction:column;gap:5px;margin-top:14px;display:flex}.detail-plugin{color:var(--blue);font:10.5px var(--mono);overflow-wrap:anywhere;border:1px solid #00000014;border-radius:8px;padding:6px 9px;display:block}.raw-json{margin:14px 0 0}.plugins-view{min-width:0}.subnav{border-bottom:1px solid var(--line);color:var(--muted);align-items:center;gap:10px;padding:10px 16px;font-size:11.5px;display:flex}.subnav>a{color:var(--blue);margin-left:auto}.segmented{background:#f1f3f5;border-radius:8px;gap:2px;padding:2px;display:flex}.segmented button{color:var(--muted);border-radius:6px;padding:4px 11px;font-size:12px}.segmented button.active{color:var(--ink);background:#fff;font-weight:600;box-shadow:0 1px 3px #00000014}.plugins-scroll{flex:1;padding:14px 16px;overflow:auto}.plugins-list{flex-direction:column;gap:9px;max-width:900px;display:flex}.plugin-card{border:1px solid var(--line);border-radius:10px;padding:11px 13px}.plugin-card-head{align-items:flex-start;gap:10px;display:flex}.plugin-icon{color:var(--blue);font:11px var(--mono);margin-top:2px}.plugin-copy{flex:1;min-width:0}.plugin-title{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}.plugin-title code{font:12px var(--mono);font-weight:500}.plugin-title small{color:var(--faint);font:10px var(--mono)}.capability,.update,.local{color:#61666b;background:#ebeef2;border-radius:4px;padding:1px 6px;font-size:10px}.update{background:var(--blue-soft);color:var(--blue)}.local{color:#dd8629;font:10px var(--mono);background:#fef5e7}.plugin-copy p{color:#61666b;margin:4px 0 7px;font-size:12px;line-height:1.6}.hook-list{flex-wrap:wrap;gap:5px;display:flex}.hook-list span{color:var(--muted);font:10px var(--mono);border:1px solid #00000014;border-radius:4px;padding:1px 6px}.switch{background:#cfd3d6;border-radius:20px;flex:0 0 34px;width:34px;height:20px;position:relative}.switch.on{background:var(--ink)}.switch i{background:#fff;border-radius:50%;width:16px;height:16px;position:absolute;top:2px;left:2px;box-shadow:0 1px 2px #0003}.switch.on i{left:16px}.plugin-add{border:1px dashed #00000029;border-radius:10px;align-items:center;gap:9px;padding:12px 13px;display:flex}.plugin-add code{color:var(--muted);font:11.5px var(--mono)}.plugin-add input{min-width:0;height:28px;font:11.5px var(--mono);border:1px solid #0000001a;border-radius:7px;flex:1;padding:0 9px}.settings-overlay,.command-palette{z-index:40;background:#0000003d;place-items:center;padding:40px;display:grid;position:fixed;inset:0}.settings-dialog{background:#fff;border-radius:14px;width:100%;max-width:880px;height:100%;max-height:620px;display:flex;overflow:hidden;box-shadow:0 24px 64px #0000003d}.settings-dialog>aside{background:var(--soft);border-right:1px solid #0000000f;flex-direction:column;flex:0 0 184px;gap:2px;width:184px;padding:12px 8px;display:flex}.settings-dialog>aside>strong{padding:4px 9px 10px;font-size:13px}.settings-tab{text-align:left;border-radius:8px;height:30px;padding:0 9px;font-size:12.5px}.settings-tab.active{background:#f1f3f5;font-weight:600}.settings-tab b{float:right;color:#61666b;font:10px var(--mono);font-weight:400}.settings-dialog>section{flex-direction:column;flex:1;min-width:0;display:flex}.settings-dialog section>header{border-bottom:1px solid #0000000f;align-items:center;height:44px;padding:0 16px;display:flex}.settings-dialog section>header strong{flex:1;font-size:13px}.settings-dialog section>header button{color:var(--muted);font-size:19px}.settings-body{flex:1;padding:14px 16px;overflow:auto}.settings-intro{border-bottom:1px solid var(--line);padding:5px 0 11px}.settings-intro small{color:var(--faint);font:9.5px var(--mono)}.settings-intro h3{font:13px var(--mono);margin:4px 0;font-weight:500}.settings-intro p{color:var(--muted);margin:0;font-size:12px}.general-row{border-bottom:1px solid #0000000f;align-items:center;gap:12px;padding:12px 0;display:flex}.general-row>div{flex:1}.general-row strong{font-size:12.5px;display:block}.general-row small{color:var(--muted);margin-top:2px;font-size:11.5px;display:block}.provider-card{border:1px solid var(--line);border-radius:10px;margin-bottom:12px;padding:12px 13px}.provider-head{align-items:center;gap:8px;margin-bottom:10px;display:flex}.provider-dot{color:var(--green);font-size:10px}.provider-head strong{font-size:12.5px}.provider-state{color:var(--green);font:10.5px var(--mono);margin-left:auto}.provider-field{align-items:center;gap:8px;margin-top:7px;display:flex}.provider-field code{color:#61666b;width:66px;font:11px var(--mono);flex:0 0 66px}.provider-field input{min-width:0;height:28px;font:11.5px var(--mono);background:#fff;border:1px solid #0000001a;border-radius:7px;flex:1;padding:0 9px}.provider-footer{align-items:center;gap:8px;margin-top:9px;display:flex}.provider-footer code{color:var(--muted);font:10.5px var(--mono)}.provider-footer button{border:1px solid var(--line);background:#fff;border-radius:7px;padding:4px 9px;font-size:11px}.provider-footer .link-button{color:var(--blue);border:0;margin-left:auto}.model-chips{flex-wrap:wrap;gap:5px;margin-top:10px;display:flex}.model-chips span{color:var(--blue);font:10.5px var(--mono);background:#e4edfd;border-radius:4px;padding:1px 7px}.add-provider{text-align:left;color:#61666b;border:1px dashed #00000029;border-radius:10px;align-items:center;gap:9px;width:100%;padding:11px 13px;display:flex}.add-provider small{color:var(--faint);font:10.5px var(--mono);margin-left:auto}.toml-toolbar{color:var(--muted);align-items:center;gap:6px;margin-bottom:10px;font-size:11.5px;display:flex}.toml-toolbar span{flex:1}.toml-toolbar button{border:1px solid var(--line);background:#fff;border-radius:7px;padding:4px 9px;font-size:11px}.toml-toolbar button.active{background:#f1f3f5;font-weight:600}.toml-toolbar .primary{background:var(--ink);color:#fff}.toml{border:1px solid var(--line);color:#61666b;border-radius:9px;min-height:420px}.command-palette{background:#0000002e}.palette-dialog{background:#fff;border:1px solid #0000001f;border-radius:12px;width:100%;max-width:600px;overflow:hidden;box-shadow:0 24px 64px #00000038}.palette-dialog>input{border:0;border-bottom:1px solid var(--line);outline:0;width:100%;padding:12px 14px}.palette-group{padding:8px}.palette-group small{color:var(--faint);font:10px var(--mono);padding:4px 6px;display:block}.palette-group button{text-align:left;width:100%;font:12px var(--mono);padding:9px 7px;display:flex}.palette-group button span{color:var(--muted);font:12px var(--sans);margin-left:16px}@keyframes pulse{50%{opacity:.3}}@media (width<=1100px){.details-panel,.details-toggle{display:none}}@media (width<=760px){.sidebar{flex-basis:216px;width:216px}.main-header{gap:7px;padding:0 10px}.active-heading small{max-width:180px}.composer-wrap,.chat-scroll{padding-left:12px;padding-right:12px}.view-tabs{margin-left:auto}.composer-hint{display:none}}@media (width<=560px){.sidebar{flex-basis:54px;width:54px}.brand-row{justify-content:center;padding:0}.brand-row strong,.version,.sidebar-actions,.sidebar-scroll,.runtime-cells,.sidebar-footer,.main-header .active-heading small{display:none}.view-tab{padding:4px 7px}.details-panel{display:none}.composer-tools{justify-content:flex-end}}.main-header{position:relative}.context-bar i:first-child{background:#c7d6f5;width:44%}.context-bar i:nth-child(2){background:#dce7fb;width:33%}.context-bar i:nth-child(3){background:#edf2fd;width:23%}.file-summary{color:var(--muted);font:10.5px var(--mono);margin:-8px 0 12px}.settings-note{color:var(--muted);margin-top:10px;font-size:11px;line-height:1.5;display:block}.extension-list{max-width:900px}.extension-list .empty-state{border:1px dashed #00000024;border-radius:10px}.subnav>a{white-space:nowrap}.plugin-card .switch{margin-left:auto}.session-menu-popover[hidden]{display:none}.empty-state{color:var(--muted);text-align:center;padding:28px 16px;font-size:12px}.settings-plugin-row{font:11.5px var(--mono);color:#61666b;border-bottom:1px solid #0000000f;padding:8px 0}.settings-body>p{color:var(--muted);font-size:12px}.provider-card input{width:100%;height:28px;font:11.5px var(--mono);border:1px solid #0000001a;border-radius:7px;margin-top:7px;padding:0 9px;display:block}.stop-button{color:var(--red);border:1px solid #ec13133d;border-radius:6px;padding:2px 8px;font-size:11px}.stop-button:disabled{opacity:.45;cursor:not-allowed}.session-menu-popover{z-index:35;background:#fff;border:1px solid #0000001a;border-radius:10px;width:224px;position:absolute;top:34px;right:0;overflow:hidden;box-shadow:0 10px 28px #00000024}.session-menu{position:relative}.session-action{text-align:left;border-bottom:1px solid #0000000a;flex-direction:column;gap:1px;width:100%;padding:8px 11px;display:flex}.session-action:hover{background:var(--soft)}.session-action strong{font-size:12px}.session-action small{color:var(--faint);font-size:10px}.plugins-page{flex-direction:column;flex:1;min-height:0;display:flex}.plugin-description{color:var(--muted);margin:4px 0 0;font-size:12px}.plugin-card{display:block}.plugin-card>.plugin-icon{margin-right:9px}:root{--starter-border:#0000001a}.starter-grid{grid-template-columns:1fr 1fr;gap:8px;width:100%;margin-top:10px;display:grid}.starter-card{border:1px solid var(--starter-border);text-align:left;background:#fff;border-radius:10px;padding:10px 12px}.starter-card:hover{background:var(--soft);border-color:#4176e666}.starter-card strong,.starter-card small{display:block}.starter-card strong{font-size:12.5px}.starter-card small{color:var(--muted);font:10.5px var(--mono);margin-top:4px}:root{--empty:#9aa0a6}.timeline-empty{color:var(--faint);font:10px var(--mono);padding:5px 8px}.timeline-turn{flex:1;min-width:4px}.timeline-strip{background:var(--blue);border-radius:3px;height:100%}.timeline-turn:nth-child(3n) .timeline-strip{background:#93c5fd}.timeline-turn:nth-child(4n) .timeline-strip{background:#f59e0b}.extension-note{color:#61666b;margin:0 0 10px;font-size:12px;line-height:1.6}.extension-table{border:1px solid var(--line);border-radius:10px;overflow:hidden}.extension-row{border-bottom:1px solid #0000000a;grid-template-columns:148px 1fr 66px;align-items:center;gap:12px;padding:9px 13px;display:grid}.extension-row:last-child{border-bottom:0}.extension-head{background:var(--soft);color:var(--faint);font:10px var(--mono);letter-spacing:.04em;text-transform:uppercase;padding-top:7px;padding-bottom:7px}.extension-owners{flex-wrap:wrap;gap:5px;min-width:0;display:flex}.extension-owners span{color:var(--blue);font:10.5px var(--mono);overflow-wrap:anywhere;background:#e4edfd;border-radius:4px;padding:1px 7px}.raw-json{border:1px solid var(--line);border-radius:8px;overflow:hidden}.raw-json summary{cursor:pointer;color:var(--muted);font:10.5px var(--mono);padding:7px 9px}.raw-json-body{border-top:1px solid var(--line);white-space:pre-wrap;margin:0;padding:9px}.detail-actions{gap:7px;margin-top:14px;display:flex}.detail-actions button{border:1px solid var(--line);color:#61666b;background:#fff;border-radius:7px;padding:5px 9px;font-size:11px}.detail-actions button:disabled{cursor:not-allowed;opacity:.5}.status-pill.running{color:var(--blue)}.status-pill.running:before{background:var(--blue);box-shadow:0 0 8px #4176e673}.palette-group button.active{background:#f1f3f5}.file-actions input{min-width:180px;height:29px;font:11.5px var(--mono);background:#fff;border:1px solid #0000001a;border-radius:7px;padding:0 9px}.file-actions input:focus{border-color:#4176e680;outline:0}.action-error{color:var(--red);margin:9px 0 0;font-size:11.5px}.provider-result{color:var(--blue);font:10.5px var(--mono);margin-top:9px;display:block}
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta name="theme-color" content="#071016">
7
+ <title>Pi Harness / Control Room</title>
8
+ <script type="module" crossorigin src="/assets/index-C4tLweAB.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-DPgRbQ4_.css">
10
+ </head>
11
+ <body>
12
+ <main id="root"></main>
13
+ </body>
14
+ </html>
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta name="theme-color" content="#071016">
7
+ <title>Pi Harness / Control Room</title>
8
+ </head>
9
+ <body>
10
+ <main id="root"></main>
11
+ <script type="module" src="/src/main.ts"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@pi-harness/web",
3
+ "version": "0.1.0",
4
+ "description": "Browser application entry for Pi Harness",
5
+ "private": true,
6
+ "type": "module",
7
+ "scripts": {
8
+ "build": "tsc -p tsconfig.build.json && vite build",
9
+ "typecheck": "tsc -p tsconfig.json",
10
+ "dev": "vite"
11
+ },
12
+ "dependencies": {
13
+ "@pi-harness/api-gateway": "0.1.0",
14
+ "@pi-harness/client-web": "0.1.0",
15
+ "@pi-harness/core": "0.1.0",
16
+ "@pi-harness/host-webserver": "0.1.0",
17
+ "@pi-harness/web-app": "0.1.0"
18
+ },
19
+ "devDependencies": {
20
+ "@types/node": "22.19.19",
21
+ "typescript": "5.9.3",
22
+ "vite": "8.2.2"
23
+ }
24
+ }
@@ -0,0 +1,44 @@
1
+ - id: agent
2
+ name: cordis:group
3
+ group: true
4
+ config:
5
+ - id: models
6
+ name: "@pi-harness/core/plugins/models"
7
+ config:
8
+ provider: !!js process.env.PI_HARNESS_PROVIDER ?? 'deepseek'
9
+ model: !!js process.env.PI_HARNESS_MODEL ?? 'deepseek-v4-flash'
10
+ refreshOnCreate: false
11
+ - id: resources
12
+ name: "@pi-harness/core/plugins/resources"
13
+ config: {}
14
+ - id: model
15
+ name: "@pi-harness/core/plugins/model"
16
+ config: {}
17
+ - id: session
18
+ name: "@pi-harness/core/plugins/session"
19
+ config:
20
+ storage: jsonl
21
+ - id: tools
22
+ name: "@pi-harness/core/plugins/tools"
23
+ config:
24
+ names:
25
+ - read
26
+ - bash
27
+ - edit
28
+ - write
29
+ - id: runtime
30
+ name: "@pi-harness/core/plugins/runtime"
31
+ config:
32
+ thinkingLevel: medium
33
+ - id: webserver
34
+ name: "@pi-harness/host-webserver"
35
+ config:
36
+ host: !!js process.env.PI_HARNESS_HOST ?? '127.0.0.1'
37
+ port: !!js Number(process.env.PI_HARNESS_PORT ?? 3080)
38
+ - id: api
39
+ name: "@pi-harness/api-gateway"
40
+ config: {}
41
+ - id: web-app
42
+ name: "@pi-harness/web-app"
43
+ config:
44
+ staticDir: !!js process.env.PI_HARNESS_WEB_DIST
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import "@pi-harness/host-webserver";
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/server/bin.ts"],"names":[],"mappings":";AAMA,OAAO,4BAA4B,CAAC"}
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { bootHarness, provideLaunchContext } from "@pi-harness/core";
6
+ import "@pi-harness/host-webserver";
7
+ const host = process.env.PI_HARNESS_HOST ?? "127.0.0.1";
8
+ const port = Number(process.env.PI_HARNESS_PORT ?? "3080");
9
+ if (!Number.isInteger(port) || port < 0 || port > 65_535)
10
+ throw new Error("PI_HARNESS_PORT must be an integer between 0 and 65535");
11
+ const loopbackHosts = new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
12
+ if (!loopbackHosts.has(host) && process.env.PI_HARNESS_ALLOW_REMOTE !== "1")
13
+ throw new Error("Refusing non-loopback PI_HARNESS_HOST; set PI_HARNESS_ALLOW_REMOTE=1 only on a trusted network");
14
+ const cwd = process.cwd();
15
+ const agentDir = process.env.PI_AGENT_DIR ?? join(homedir(), ".pi", "agent");
16
+ const staticDir = fileURLToPath(new URL("../dist", import.meta.url));
17
+ const profilePath = fileURLToPath(new URL("../profile/cordis.yml", import.meta.url));
18
+ process.env.PI_HARNESS_WEB_DIST = staticDir;
19
+ process.env.PI_HARNESS_HOST = host;
20
+ process.env.PI_HARNESS_PORT = String(port);
21
+ const signals = process.platform === "win32" ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
22
+ const startupAbort = new AbortController();
23
+ let shuttingDown = false;
24
+ let resolveExit;
25
+ const processExit = new Promise((resolve) => { resolveExit = resolve; });
26
+ let harness;
27
+ const shutdown = async (signal) => {
28
+ if (shuttingDown)
29
+ return;
30
+ shuttingDown = true;
31
+ startupAbort.abort(signal);
32
+ if (harness !== undefined) {
33
+ let disposed = false;
34
+ await Promise.race([
35
+ harness.dispose().then(() => { disposed = true; }),
36
+ new Promise((resolve) => setTimeout(resolve, 5_000)),
37
+ ]);
38
+ if (!disposed) {
39
+ process.stderr.write("Pi Harness web shutdown timed out\n");
40
+ process.exit(signal === "SIGINT" ? 130 : signal === "SIGHUP" ? 129 : 143);
41
+ return;
42
+ }
43
+ }
44
+ process.exitCode = signal === "SIGINT" ? 130 : signal === "SIGHUP" ? 129 : 143;
45
+ resolveExit?.();
46
+ };
47
+ for (const signal of signals) {
48
+ process.once(signal, () => { void shutdown(signal); });
49
+ }
50
+ try {
51
+ harness = await bootHarness({
52
+ configPath: profilePath,
53
+ signal: startupAbort.signal,
54
+ prepare(context) {
55
+ provideLaunchContext(context, { cwd, agentDir, args: [], requestExit() { } });
56
+ },
57
+ });
58
+ process.stdout.write("Pi Harness web console: " + harness.context.webServer.url + "\n");
59
+ await processExit;
60
+ }
61
+ catch (error) {
62
+ if (!shuttingDown) {
63
+ process.exitCode = 1;
64
+ process.stderr.write((error instanceof Error ? error.message : String(error)) + "\n");
65
+ }
66
+ }
67
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/server/bin.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,4BAA4B,CAAC;AAEpC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,WAAW,CAAC;AACxD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,MAAM,CAAC,CAAC;AAC3D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,MAAM;IAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;AACpI,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1E,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,GAAG;IAAE,MAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;AAC/L,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AAC7E,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrE,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrF,OAAO,CAAC,GAAG,CAAC,mBAAmB,GAAG,SAAS,CAAC;AAC5C,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,IAAI,CAAC;AACnC,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;AAC3C,MAAM,OAAO,GAAqB,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AACzH,MAAM,YAAY,GAAG,IAAI,eAAe,EAAE,CAAC;AAC3C,IAAI,YAAY,GAAG,KAAK,CAAC;AACzB,IAAI,WAAqC,CAAC;AAC1C,MAAM,WAAW,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,GAAG,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/E,IAAI,OAA4D,CAAC;AACjE,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAsB,EAAiB,EAAE;IAC/D,IAAI,YAAY;QAAE,OAAO;IACzB,YAAY,GAAG,IAAI,CAAC;IACpB,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,OAAO,CAAC,IAAI,CAAC;YACjB,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAClD,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;SAC3D,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;YAC5D,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC1E,OAAO;QACT,CAAC;IACH,CAAC;IACD,OAAO,CAAC,QAAQ,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAC/E,WAAW,EAAE,EAAE,CAAC;AAClB,CAAC,CAAC;AACF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AACD,IAAI,CAAC;IACH,OAAO,GAAG,MAAM,WAAW,CAAC;QAC1B,UAAU,EAAE,WAAW;QACvB,MAAM,EAAE,YAAY,CAAC,MAAM;QAC3B,OAAO,CAAC,OAAO;YACb,oBAAoB,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,KAAI,CAAC,EAAE,CAAC,CAAC;QAC/E,CAAC;KACF,CAAC,CAAC;IACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACxF,MAAM,WAAW,CAAC;AACpB,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACxF,CAAC;AACH,CAAC"}
@@ -0,0 +1,84 @@
1
+ const commandName = (button: HTMLButtonElement): string => button.firstChild?.textContent?.trim() ?? "";
2
+
3
+ export function installCommandPalette(root: HTMLElement): () => void {
4
+ const palette = root.querySelector<HTMLElement>("[data-command-palette]");
5
+ const input = root.querySelector<HTMLInputElement>("[data-command-input]");
6
+ const prompt = root.querySelector<HTMLTextAreaElement>("[data-prompt]");
7
+ const trigger = root.querySelector<HTMLElement>("[data-command]");
8
+ const permission = root.querySelector<HTMLButtonElement>("[data-permission]");
9
+ if (!palette || !input || !prompt) return () => {};
10
+ const buttons = [...palette.querySelectorAll<HTMLButtonElement>(".palette-group button")];
11
+ let activeIndex = 0;
12
+
13
+ const visibleButtons = () => buttons.filter((button) => !button.hidden);
14
+ const focusActive = () => {
15
+ const visible = visibleButtons();
16
+ if (visible.length === 0) return;
17
+ activeIndex = Math.max(0, Math.min(activeIndex, visible.length - 1));
18
+ visible.forEach((button, index) => button.classList.toggle("active", index === activeIndex));
19
+ };
20
+ const open = (query = "") => {
21
+ palette.hidden = false;
22
+ input.value = query;
23
+ activeIndex = 0;
24
+ filter();
25
+ input.focus();
26
+ };
27
+ const close = () => {
28
+ palette.hidden = true;
29
+ input.value = "";
30
+ buttons.forEach((button) => { button.hidden = false; button.classList.remove("active"); });
31
+ };
32
+ const filter = () => {
33
+ const query = input.value.trim().toLowerCase();
34
+ buttons.forEach((button) => { button.hidden = query.length > 0 && !button.textContent?.toLowerCase().includes(query); });
35
+ focusActive();
36
+ };
37
+ const select = (button: HTMLButtonElement) => {
38
+ const command = commandName(button);
39
+ if (!command) return;
40
+ prompt.value = command + " ";
41
+ close();
42
+ prompt.focus();
43
+ };
44
+ const onTrigger = () => open();
45
+ const onInput = () => filter();
46
+ const onKeydown = (event: KeyboardEvent) => {
47
+ if (event.key === "Escape") { close(); return; }
48
+ const visible = visibleButtons();
49
+ if (event.key === "ArrowDown" && visible.length > 0) { event.preventDefault(); activeIndex = (activeIndex + 1) % visible.length; focusActive(); }
50
+ if (event.key === "ArrowUp" && visible.length > 0) { event.preventDefault(); activeIndex = (activeIndex - 1 + visible.length) % visible.length; focusActive(); }
51
+ if (event.key === "Enter" && visible.length > 0) { event.preventDefault(); select(visible[activeIndex]!); }
52
+ };
53
+ const onPromptInput = () => {
54
+ const value = prompt.value;
55
+ if (value.startsWith("/")) open(value.slice(1));
56
+ };
57
+ const onBackdrop = (event: MouseEvent) => { if (event.target === palette) close(); };
58
+ const onCommandClick = (event: Event) => select(event.currentTarget as HTMLButtonElement);
59
+ const onPermission = () => {
60
+ const asking = permission?.getAttribute("aria-pressed") !== "true";
61
+ if (permission) {
62
+ permission.setAttribute("aria-pressed", String(asking));
63
+ permission.textContent = asking ? "● 改动前询问" : "● 自动允许";
64
+ permission.title = "权限策略仅在当前浏览器会话中保存";
65
+ }
66
+ };
67
+ trigger?.addEventListener("click", onTrigger);
68
+ input.addEventListener("input", onInput);
69
+ input.addEventListener("keydown", onKeydown);
70
+ prompt.addEventListener("input", onPromptInput);
71
+ palette.addEventListener("click", onBackdrop);
72
+ buttons.forEach((button) => button.addEventListener("click", onCommandClick));
73
+ permission?.setAttribute("aria-pressed", "true");
74
+ permission?.addEventListener("click", onPermission);
75
+ return () => {
76
+ trigger?.removeEventListener("click", onTrigger);
77
+ input.removeEventListener("input", onInput);
78
+ input.removeEventListener("keydown", onKeydown);
79
+ prompt.removeEventListener("input", onPromptInput);
80
+ palette.removeEventListener("click", onBackdrop);
81
+ buttons.forEach((button) => button.removeEventListener("click", onCommandClick));
82
+ permission?.removeEventListener("click", onPermission);
83
+ };
84
+ }
@@ -0,0 +1,42 @@
1
+ async function readDiff(path: string): Promise<string> {
2
+ const response = await fetch(`/api/files/diff?path=${encodeURIComponent(path)}`);
3
+ const payload = await response.json() as { diff?: unknown; error?: unknown };
4
+ if (!response.ok) throw new Error(typeof payload.error === "string" ? payload.error : `Diff request failed (${response.status})`);
5
+ return typeof payload.diff === "string" && payload.diff.length > 0 ? payload.diff : "没有可显示的差异(可能是未跟踪文件或工作区已更新)。";
6
+ }
7
+
8
+ export function installFileDiff(root: HTMLElement): () => void {
9
+ const host = root.querySelector<HTMLElement>("[data-files]");
10
+ const details = root.querySelector<HTMLElement>("[data-details-panel]");
11
+ const raw = root.querySelector<HTMLElement>(".raw-json");
12
+ const title = root.querySelector<HTMLElement>("[data-detail-title]");
13
+ if (!host || !details || !raw || !title) return () => {};
14
+ const attach = () => {
15
+ host.querySelectorAll<HTMLElement>(".file-row").forEach((row) => {
16
+ if (row.querySelector("[data-file-diff]")) return;
17
+ const path = row.querySelector("code")?.textContent?.trim();
18
+ if (!path) return;
19
+ const button = row.querySelector<HTMLButtonElement>("button") ?? document.createElement("button");
20
+ button.type = "button";
21
+ button.dataset.fileDiff = "true";
22
+ button.textContent = "查看差异";
23
+ button.addEventListener("click", () => {
24
+ button.disabled = true;
25
+ void readDiff(path).then((diff) => {
26
+ details.hidden = false;
27
+ title.textContent = `文件差异 · ${path}`;
28
+ raw.textContent = diff;
29
+ }).catch((error: unknown) => {
30
+ details.hidden = false;
31
+ title.textContent = `文件差异 · ${path}`;
32
+ raw.textContent = error instanceof Error ? error.message : String(error);
33
+ }).finally(() => { button.disabled = false; });
34
+ });
35
+ if (!button.parentElement) row.append(button);
36
+ });
37
+ };
38
+ const observer = new MutationObserver(attach);
39
+ observer.observe(host, { childList: true, subtree: true });
40
+ attach();
41
+ return () => observer.disconnect();
42
+ }
@@ -0,0 +1,12 @@
1
+ import { AppWebEntry } from "@pi-harness/client-web";
2
+ import "./style.css";
3
+ import "./runtime.css";
4
+
5
+ const root = document.getElementById("root");
6
+ if (!(root instanceof HTMLElement)) throw new Error("Pi Harness web app is missing #root");
7
+ const entry = new AppWebEntry(root);
8
+ try {
9
+ void entry.run();
10
+ } catch (error: unknown) {
11
+ root.textContent = error instanceof Error ? error.message : String(error);
12
+ }
@@ -0,0 +1,4 @@
1
+ .status-pill.running { color: var(--blue); }
2
+ .status-pill.running::before { background: var(--blue); box-shadow: 0 0 8px rgba(65, 118, 230, .45); }
3
+ .palette-group button.active { background: #f1f3f5; }
4
+ .file-actions input{height:29px;min-width:180px;padding:0 9px;border:1px solid rgba(0,0,0,.1);border-radius:7px;background:#fff;font:11.5px var(--mono)}.file-actions input:focus{border-color:rgba(65,118,230,.5);outline:0}.action-error{margin:9px 0 0;color:var(--red);font-size:11.5px}.provider-result{display:block;margin-top:9px;color:var(--blue);font:10.5px var(--mono)}
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { bootHarness, provideLaunchContext } from "@pi-harness/core";
7
+ import "@pi-harness/host-webserver";
8
+
9
+ const host = process.env.PI_HARNESS_HOST ?? "127.0.0.1";
10
+ const port = Number(process.env.PI_HARNESS_PORT ?? "3080");
11
+ if (!Number.isInteger(port) || port < 0 || port > 65_535) throw new Error("PI_HARNESS_PORT must be an integer between 0 and 65535");
12
+ const loopbackHosts = new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
13
+ if (!loopbackHosts.has(host) && process.env.PI_HARNESS_ALLOW_REMOTE !== "1") throw new Error("Refusing non-loopback PI_HARNESS_HOST; set PI_HARNESS_ALLOW_REMOTE=1 only on a trusted network");
14
+ const cwd = process.cwd();
15
+ const agentDir = process.env.PI_AGENT_DIR ?? join(homedir(), ".pi", "agent");
16
+ const staticDir = fileURLToPath(new URL("../dist", import.meta.url));
17
+ const profilePath = fileURLToPath(new URL("../profile/cordis.yml", import.meta.url));
18
+ process.env.PI_HARNESS_WEB_DIST = staticDir;
19
+ process.env.PI_HARNESS_HOST = host;
20
+ process.env.PI_HARNESS_PORT = String(port);
21
+ const signals: NodeJS.Signals[] = process.platform === "win32" ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
22
+ const startupAbort = new AbortController();
23
+ let shuttingDown = false;
24
+ let resolveExit: (() => void) | undefined;
25
+ const processExit = new Promise<void>((resolve) => { resolveExit = resolve; });
26
+ let harness: Awaited<ReturnType<typeof bootHarness>> | undefined;
27
+ const shutdown = async (signal: NodeJS.Signals): Promise<void> => {
28
+ if (shuttingDown) return;
29
+ shuttingDown = true;
30
+ startupAbort.abort(signal);
31
+ if (harness !== undefined) {
32
+ let disposed = false;
33
+ await Promise.race([
34
+ harness.dispose().then(() => { disposed = true; }),
35
+ new Promise<void>((resolve) => setTimeout(resolve, 5_000)),
36
+ ]);
37
+ if (!disposed) {
38
+ process.stderr.write("Pi Harness web shutdown timed out\n");
39
+ process.exit(signal === "SIGINT" ? 130 : signal === "SIGHUP" ? 129 : 143);
40
+ return;
41
+ }
42
+ }
43
+ process.exitCode = signal === "SIGINT" ? 130 : signal === "SIGHUP" ? 129 : 143;
44
+ resolveExit?.();
45
+ };
46
+ for (const signal of signals) {
47
+ process.once(signal, () => { void shutdown(signal); });
48
+ }
49
+ try {
50
+ harness = await bootHarness({
51
+ configPath: profilePath,
52
+ signal: startupAbort.signal,
53
+ prepare(context) {
54
+ provideLaunchContext(context, { cwd, agentDir, args: [], requestExit() {} });
55
+ },
56
+ });
57
+ process.stdout.write("Pi Harness web console: " + harness.context.webServer.url + "\n");
58
+ await processExit;
59
+ } catch (error) {
60
+ if (!shuttingDown) {
61
+ process.exitCode = 1;
62
+ process.stderr.write((error instanceof Error ? error.message : String(error)) + "\n");
63
+ }
64
+ }
@@ -0,0 +1,7 @@
1
+ :root{color-scheme:light;--ink:#0f1115;--muted:#81858c;--faint:#adb2b8;--line:rgba(0,0,0,.09);--soft:#f9fafb;--blue:#4176e6;--blue-soft:#edf3fe;--green:#22c55e;--red:#ec1313;--amber:#f59e0b;--mono:"JetBrains Mono","SFMono-Regular",Consolas,monospace;--sans:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif}*{box-sizing:border-box}html,body,#root{margin:0;width:100%;height:100%;overflow:hidden}body{background:#fff;color:var(--ink);font:13px/1.5 var(--sans);-webkit-font-smoothing:antialiased}button,input,textarea,select{font:inherit;color:inherit}button{border:0;background:none;cursor:pointer}button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline:2px solid rgba(65,118,230,.45);outline-offset:1px}[hidden]{display:none!important}.app-frame{display:flex;width:100%;height:100%;overflow:hidden;background:#fff}.sidebar{width:264px;flex:0 0 264px;display:flex;flex-direction:column;min-height:0;background:var(--soft);border-right:1px solid rgba(0,0,0,.06)}.brand-row{height:48px;flex:0 0 48px;display:flex;align-items:center;gap:9px;padding:0 14px}.brand-row strong{font-size:13px;font-weight:600;letter-spacing:-.1px}.pi-mark{display:grid;place-items:center;width:22px;height:22px;flex:none;border-radius:6px;background:var(--ink);color:#fff;font:13px var(--mono)}.pi-mark.large{width:38px;height:38px;border-radius:11px;font-size:19px}.version{margin-left:auto;color:var(--faint);font:10px var(--mono)}.sidebar-actions{display:flex;flex-direction:column;gap:8px;padding:0 10px 10px}.new-session{height:32px;display:flex;align-items:center;justify-content:center;gap:6px;border-radius:8px;background:var(--ink);color:#fff;font-size:12.5px;font-weight:500}.new-session:hover,.send-button:hover{background:#43454a}.sidebar-actions input{width:100%;height:30px;border:1px solid rgba(0,0,0,.1);border-radius:8px;background:#fff;padding:0 10px;font-size:12px;outline:none}.sidebar-scroll{flex:1;min-height:0;overflow:auto;padding:0 8px 8px}.session-group{margin-bottom:8px}.group-label{padding:6px 8px 4px;color:var(--faint);font-size:10px;letter-spacing:.04em}.session-row{display:flex;align-items:center;gap:7px;width:100%;padding:7px 9px;border-radius:8px;text-align:left}.session-row:hover{background:#f1f3f5}.session-row.active{background:#ebeef2}.session-dot{width:6px;height:6px;flex:none;border-radius:50%;background:#cfd3d6}.session-dot.running{background:var(--green);animation:pulse 1.4s ease-in-out infinite}.session-dot.ok{background:var(--green)}.session-dot.warn{background:var(--amber)}.session-dot.error{background:var(--red)}.session-copy{display:flex;flex-direction:column;gap:2px;min-width:0}.session-copy strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12.5px;font-weight:600}.session-copy small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--faint);font:10px var(--mono)}.runtime-cells{display:flex;flex-wrap:wrap;gap:4px 12px;padding:8px 19px 9px;color:var(--faint);font:9.5px var(--mono);border-top:1px solid rgba(0,0,0,.06)}.runtime-cells span{display:flex;gap:5px}.runtime-cells b{font-weight:400}.runtime-cells strong{color:#61666b;font-weight:400}.sidebar-footer{display:flex;flex-direction:column;gap:2px;padding:6px 10px 8px;border-top:1px solid rgba(0,0,0,.06)}.sidebar-link{display:flex;align-items:center;gap:9px;height:30px;padding:0 9px;border-radius:8px;text-align:left;font-size:12.5px}.sidebar-link:hover{background:#f1f3f5}.sidebar-link span:nth-child(2){flex:1}.sidebar-link b{padding:1px 6px;border-radius:20px;background:#ebeef2;color:#61666b;font:10px var(--mono);font-weight:400}.link-glyph{color:var(--blue);font:11.5px var(--mono)}.main-pane{display:flex;flex:1;min-width:0;flex-direction:column}.main-header{height:48px;flex:0 0 48px;display:flex;align-items:center;gap:12px;padding:0 16px;border-bottom:1px solid rgba(0,0,0,.06)}.active-heading{display:flex;min-width:0;flex-direction:column}.active-heading strong,.active-heading small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.active-heading strong{font-size:13px;font-weight:600}.active-heading small{color:var(--faint);font:10px var(--mono)}.header-spacer{flex:1}.run-indicator{display:flex;align-items:center;gap:6px;flex:none;color:#61666b;font:10.5px var(--mono)}.run-indicator>span{width:6px;height:6px;border-radius:50%;background:var(--green);animation:pulse 1.4s ease-in-out infinite}.run-indicator button{padding:2px 8px;border:1px solid rgba(236,19,19,.24);border-radius:6px;color:var(--red);font-size:11px}.run-indicator.running>span{background:var(--blue)}.view-tabs{display:flex;gap:2px;padding:2px;border-radius:8px;background:#f1f3f5}.view-tab{padding:4px 11px;border-radius:6px;color:var(--muted);font-size:12px}.view-tab.active{background:#fff;color:var(--ink);box-shadow:0 1px 3px rgba(0,0,0,.08);font-weight:600}.session-menu,.details-toggle{height:28px;border:1px solid rgba(0,0,0,.1);border-radius:8px;background:#fff;color:#61666b}.session-menu{width:28px;font-size:15px}.details-toggle{padding:0 9px;font-size:12px}.session-menu:hover,.details-toggle:hover{background:#f1f3f5}.view-host{display:flex;flex:1;min-height:0;flex-direction:column}.view-panel{display:flex;flex:1;min-height:0;flex-direction:column}.chat-scroll{flex:1;min-height:0;overflow-y:auto;padding:20px 24px 4px}.turn{max-width:748px;margin:0 auto 16px;font-size:13.5px;line-height:1.78}.turn.user{display:flex;justify-content:flex-end}.user-bubble{max-width:84%;padding:10px 14px;border-radius:12px;background:var(--blue-soft);white-space:pre-wrap}.turn-text{margin:0;white-space:pre-wrap}.reasoning-head{display:flex;align-items:center;gap:6px;padding:0;color:var(--muted);font-size:11.5px}.reasoning-head .caret{color:var(--faint);font-size:9px}.reasoning-body{display:none;margin:6px 0 0;padding-left:11px;border-left:2px solid #ebeef2;color:#61666b;font-size:12.5px;line-height:1.75;white-space:pre-wrap}.reasoning:hover .reasoning-body{display:block}.plugin-event{display:flex;align-items:center;gap:8px;height:30px;padding:0 11px;border:1px dashed rgba(65,118,230,.35);border-radius:8px;background:#f7faff;color:var(--blue);font:11px var(--mono)}.plugin-event>span:nth-last-child(1){overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#61666b;font:12px var(--sans)}.plugin-hook{padding:1px 6px;border-radius:4px;background:#e4edfd;color:#81858c!important;font:10px var(--mono)!important}.tool-card,.approval-card,.subagent-card,.todo-card{border:1px solid var(--line);border-radius:10px;background:#fff;overflow:hidden}.tool-head,.subagent-head{display:flex;align-items:center;gap:9px;width:100%;min-height:34px;padding:7px 11px;text-align:left;background:#fff}.tool-head{font:11.5px var(--mono)}.tool-glyph{width:12px;color:var(--muted)}.tool-target,.subagent-goal{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--muted);font-size:11px}.tool-head .tool-target,.subagent-goal{flex:1}.tool-stat{color:var(--muted)}.tool-detail-link{color:var(--blue);font:10.5px var(--sans)}.tool-output,.diff-preview,.toml{margin:0;padding:10px 12px;border-top:1px solid rgba(0,0,0,.06);background:var(--soft);white-space:pre-wrap;word-break:break-word;color:#61666b;font:11.5px/1.7 var(--mono)}.diff-line{display:flex;gap:10px;padding:0 8px;font:11.5px/1.7 var(--mono)}.diff-line.added{background:#e6faed}.diff-line.removed{background:#fff0f0}.diff-no{width:30px;color:var(--faint);text-align:right}.diff-sign{width:8px;color:var(--green)}.diff-line.removed .diff-sign{color:var(--red)}.approval-card{padding:11px 13px;background:#fffaf0;border-color:rgba(245,158,11,.4)}.approval-card pre{padding:8px 0;background:transparent;border:0}.approval-actions{display:flex;gap:7px;margin-top:4px}.approval-actions button,.plugin-add button{padding:5px 11px;border:1px solid var(--line);border-radius:7px;background:#fff;font-size:11.5px}.approval-actions .primary,.plugin-add .primary{background:var(--ink);color:#fff}.approval-actions .danger{color:var(--red)}.subagent-head{font-size:12.5px}.subagent-glyph{color:#679efe;font:11px var(--mono)}.subagent-preset{padding:1px 6px;border-radius:4px;background:#e4edfd;color:#81858c;font:10.5px var(--mono)}.subagent-duration{color:var(--faint);font:10.5px var(--mono)}.subagent-body{display:block;padding:4px 11px 9px;border-top:1px solid rgba(0,0,0,.06)}.subagent-lineage{display:block;padding:6px 0 4px;color:var(--faint);font:10px var(--mono)}.subagent-step{display:flex;align-items:center;gap:8px;padding:4px 0;border-left:2px solid #e4edfd;padding-left:10px}.subagent-step code{width:42px;color:var(--muted);font:10.5px var(--mono)}.subagent-step span{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#61666b;font:11px var(--mono)}.subagent-step small{color:var(--faint);font:10px var(--mono)}.subagent-body p{margin:8px 0 0;padding-top:8px;border-top:1px solid rgba(0,0,0,.06)}.todo-head{display:flex;align-items:center;gap:8px;height:32px;padding:0 11px;border-bottom:1px solid rgba(0,0,0,.06)}.todo-head small{color:var(--faint);font:10.5px var(--mono)}.todo-row{display:flex;align-items:flex-start;gap:9px;padding:7px 11px;border-bottom:1px solid rgba(0,0,0,.04)}.todo-row.done{color:var(--muted);text-decoration:line-through}.todo-mark{color:var(--green);font:11px var(--mono)}.stats-row{display:flex;gap:14px;flex-wrap:wrap;color:var(--faint);font:10.5px var(--mono)}.composer-wrap{flex:0 0 auto;padding:8px 24px 14px}.context-line{display:flex;max-width:748px;margin:0 auto 8px;align-items:center;gap:9px;color:var(--faint);font:10.5px var(--mono)}.context-line b{color:var(--muted);font-weight:400}.context-line button{padding:0;color:var(--blue);font-size:11px}.context-bar{display:flex;flex:1;height:4px;overflow:hidden;border-radius:3px;background:#ebeef2}.context-bar i{height:100%}.context-bar.expanded{height:8px}.composer{max-width:748px;margin:0 auto;border:1px solid rgba(0,0,0,.12);border-radius:12px;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.03);overflow:hidden}.composer textarea{display:block;width:100%;min-height:65px;padding:11px 13px 4px;border:0;outline:0;resize:none;color:var(--ink);font-size:13.5px;line-height:1.7;background:transparent}.composer-tools{display:flex;align-items:center;gap:6px;padding:6px 8px 8px}.composer-tools select,.tool-chip{height:26px;padding:0 7px;border:1px solid rgba(0,0,0,.1);border-radius:7px;background:#fff;font:11px var(--mono)}.tool-chip{padding:0 9px;color:#61666b;font-family:var(--sans);font-size:11.5px}.composer-hint{flex:1;color:#cfd3d6;font:10px var(--mono);text-align:right}.send-button{width:28px;height:28px;border-radius:8px;background:var(--ink);color:#fff;font-size:15px}.send-button:disabled{cursor:not-allowed;opacity:.45}.new-session-screen{max-width:580px;margin:0 auto;padding:40px 0;display:flex;align-items:center;flex-direction:column;gap:11px;text-align:center}.new-session-screen h2{margin:0;font-size:16.5px}.new-session-screen p{margin:0;color:var(--muted)}.workspace-picker{display:grid;gap:6px;width:100%;margin-top:12px;text-align:left}.workspace-row{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;border:1px solid var(--line);border-radius:9px;background:#fff;text-align:left}.workspace-row:hover{background:var(--soft);border-color:rgba(65,118,230,.4)}.workspace-row code{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:12px var(--mono)}.workspace-row small{display:block;margin-top:3px;color:var(--faint);font:10px var(--mono)}.workspace-row .live{color:var(--green)}.workspace-row .offline{color:#cfd3d6}.effective-config{display:flex;flex-wrap:wrap;align-items:center;gap:10px;width:100%;padding:9px 12px;border:1px solid rgba(0,0,0,.08);border-radius:10px;background:var(--soft);text-align:left}.effective-config code{color:var(--faint);font:10.5px var(--mono)}.effective-config span{color:#61666b;font:10.5px var(--mono)}.trajectory-summary{flex:none;padding:12px 16px 10px;border-bottom:1px solid var(--line);color:var(--muted);font-size:11.5px}.trajectory-summary b{margin-left:9px;color:var(--faint);font:10.5px var(--mono);font-weight:400}.timeline{display:flex;gap:3px;height:26px;margin-top:8px}.timeline-turn{display:flex;align-items:stretch;padding:0;background:#ebeef2;border-radius:3px;overflow:hidden}.timeline-strip{display:block;width:100%;opacity:.9}.source-filters{display:flex;align-items:center;gap:6px;flex:none;padding:9px 16px;border-bottom:1px solid var(--line);flex-wrap:wrap}.filter{display:flex;align-items:center;gap:6px;padding:3px 9px;border:1px solid rgba(0,0,0,.1);border-radius:20px;color:var(--muted);font-size:11.5px}.filter.active{border-color:rgba(65,118,230,.35);background:var(--blue-soft);color:var(--blue)}.filter b{color:var(--faint);font:10px var(--mono);font-weight:400}.event-count{margin-left:auto;color:var(--faint);font:10.5px var(--mono)}.event-table{flex:1;min-height:0;overflow:auto}.event-head,.event-row{display:grid;grid-template-columns:78px 132px 1fr 88px 68px;gap:12px;align-items:center;padding:7px 16px}.event-head{background:var(--soft);border-bottom:1px solid rgba(0,0,0,.06);color:var(--faint);font:10px var(--mono);letter-spacing:.04em;text-transform:uppercase}.event-row{width:100%;border-bottom:1px solid rgba(0,0,0,.04);text-align:left;font-size:12px}.event-row:hover{background:var(--soft)}.event-row>span,.event-row code{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.event-row>span:first-child,.event-row>span:last-child{color:var(--faint);font:10.5px var(--mono)}.event-row strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400}.event-row>span:nth-child(2){display:flex;align-items:center;gap:7px;color:#61666b;font:11px var(--mono)}.event-dot{width:6px;height:6px;flex:none;border-radius:2px;background:var(--blue)}.files-content{max-width:820px;padding:18px 24px}.files-title{display:flex;align-items:baseline;gap:10px;margin-bottom:14px}.files-title strong{font-size:13px}.files-title span{color:var(--faint);font:11px var(--mono)}.file-list{border:1px solid var(--line);border-radius:10px;overflow:hidden}.file-row{display:flex;align-items:center;gap:12px;padding:10px 13px;border-bottom:1px solid rgba(0,0,0,.04)}.file-row:last-child{border-bottom:0}.file-row code{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:12px var(--mono)}.file-kind{padding:1px 6px;border-radius:4px;background:#f1f3f5;color:#61666b;font:10px var(--mono)}.file-kind.new{background:#e6faed;color:#16a34a}.file-row .add{color:var(--green);font:11px var(--mono)}.file-row .del{color:var(--red);font:11px var(--mono)}.diff-button{color:var(--blue);font-size:11.5px}.file-actions{display:flex;gap:8px;margin-top:12px}.file-actions button{padding:6px 11px;border:1px solid var(--line);border-radius:7px;background:#fff;font-size:11.5px}.file-actions .primary{background:var(--ink);color:#fff}.details-panel{width:336px;flex:0 1 336px;min-width:268px;border-left:1px solid rgba(0,0,0,.1);background:#fff}.details-panel>header{height:40px;display:flex;align-items:center;gap:8px;padding:0 12px;border-bottom:1px solid rgba(0,0,0,.06)}.details-panel>header strong{flex:1;font-size:13px}.details-panel>header button{color:var(--muted);font-size:19px;line-height:1}.details-body{padding:12px;overflow:auto}.detail-stats{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin-bottom:12px}.detail-stats>div{padding:9px;border:1px solid rgba(0,0,0,.08);border-radius:8px}.detail-stats small,.detail-section>small{display:block;color:var(--faint);font:9.5px var(--mono);letter-spacing:.04em}.detail-stats b{display:block;margin-top:2px;font:12.5px var(--mono);font-weight:400}.detail-section{display:flex;margin-top:14px;flex-direction:column;gap:5px}.detail-plugin{display:block;padding:6px 9px;border:1px solid rgba(0,0,0,.08);border-radius:8px;color:var(--blue);font:10.5px var(--mono);overflow-wrap:anywhere}.raw-json{margin:14px 0 0}.plugins-view{min-width:0}.plugins-page{display:flex;min-height:0;flex:1;flex-direction:column}.subnav{display:flex;align-items:center;gap:10px;padding:10px 16px;border-bottom:1px solid var(--line);color:var(--muted);font-size:11.5px}.subnav>a{margin-left:auto;color:var(--blue)}.segmented{display:flex;gap:2px;padding:2px;border-radius:8px;background:#f1f3f5}.segmented button{padding:4px 11px;border-radius:6px;color:var(--muted);font-size:12px}.segmented button.active{background:#fff;color:var(--ink);box-shadow:0 1px 3px rgba(0,0,0,.08);font-weight:600}.plugins-scroll{flex:1;overflow:auto;padding:14px 16px}.plugins-list{max-width:900px;display:flex;flex-direction:column;gap:9px}.plugin-card{border:1px solid var(--line);border-radius:10px;padding:11px 13px}.plugin-card-head{display:flex;align-items:flex-start;gap:10px}.plugin-icon{margin-top:2px;color:var(--blue);font:11px var(--mono)}.plugin-copy{flex:1;min-width:0}.plugin-title{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}.plugin-title code{font:12px var(--mono);font-weight:500}.plugin-title small{color:var(--faint);font:10px var(--mono)}.capability,.update,.local{padding:1px 6px;border-radius:4px;background:#ebeef2;color:#61666b;font-size:10px}.update{background:var(--blue-soft);color:var(--blue)}.local{background:#fef5e7;color:#dd8629;font:10px var(--mono)}.plugin-copy p{margin:4px 0 7px;color:#61666b;font-size:12px;line-height:1.6}.hook-list{display:flex;flex-wrap:wrap;gap:5px}.hook-list span{padding:1px 6px;border:1px solid rgba(0,0,0,.08);border-radius:4px;color:var(--muted);font:10px var(--mono)}.switch{position:relative;width:34px;height:20px;flex:0 0 34px;border-radius:20px;background:#cfd3d6}.switch.on{background:var(--ink)}.switch i{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2)}.switch.on i{left:16px}.plugin-add{display:flex;align-items:center;gap:9px;padding:12px 13px;border:1px dashed rgba(0,0,0,.16);border-radius:10px}.plugin-add code{color:var(--muted);font:11.5px var(--mono)}.plugin-add input{flex:1;min-width:0;height:28px;border:1px solid rgba(0,0,0,.1);border-radius:7px;padding:0 9px;font:11.5px var(--mono)}.settings-overlay,.command-palette{position:fixed;inset:0;z-index:40;display:grid;place-items:center;padding:40px;background:rgba(0,0,0,.24)}.settings-dialog{display:flex;width:100%;max-width:880px;height:100%;max-height:620px;overflow:hidden;border-radius:14px;background:#fff;box-shadow:0 24px 64px rgba(0,0,0,.24)}.settings-dialog>aside{display:flex;width:184px;flex:0 0 184px;padding:12px 8px;flex-direction:column;gap:2px;background:var(--soft);border-right:1px solid rgba(0,0,0,.06)}.settings-dialog>aside>strong{padding:4px 9px 10px;font-size:13px}.settings-tab{height:30px;padding:0 9px;border-radius:8px;text-align:left;font-size:12.5px}.settings-tab.active{background:#f1f3f5;font-weight:600}.settings-tab b{float:right;color:#61666b;font:10px var(--mono);font-weight:400}.settings-dialog>section{display:flex;min-width:0;flex:1;flex-direction:column}.settings-dialog section>header{height:44px;display:flex;align-items:center;padding:0 16px;border-bottom:1px solid rgba(0,0,0,.06)}.settings-dialog section>header strong{flex:1;font-size:13px}.settings-dialog section>header button{color:var(--muted);font-size:19px}.settings-body{flex:1;overflow:auto;padding:14px 16px}.settings-intro{padding:5px 0 11px;border-bottom:1px solid var(--line)}.settings-intro small{color:var(--faint);font:9.5px var(--mono)}.settings-intro h3{margin:4px 0;font:13px var(--mono);font-weight:500}.settings-intro p{margin:0;color:var(--muted);font-size:12px}.general-row{display:flex;align-items:center;gap:12px;padding:12px 0;border-bottom:1px solid rgba(0,0,0,.06)}.general-row>div{flex:1}.general-row strong{display:block;font-size:12.5px}.general-row small{display:block;margin-top:2px;color:var(--muted);font-size:11.5px}.provider-card{margin-bottom:12px;padding:12px 13px;border:1px solid var(--line);border-radius:10px}.provider-head{display:flex;align-items:center;gap:8px;margin-bottom:10px}.provider-dot{color:var(--green);font-size:10px}.provider-head strong{font-size:12.5px}.provider-state{margin-left:auto;color:var(--green);font:10.5px var(--mono)}.provider-field{display:flex;align-items:center;gap:8px;margin-top:7px}.provider-field code{width:66px;flex:0 0 66px;color:#61666b;font:11px var(--mono)}.provider-field input{flex:1;min-width:0;height:28px;border:1px solid rgba(0,0,0,.1);border-radius:7px;padding:0 9px;background:#fff;font:11.5px var(--mono)}.provider-footer{display:flex;align-items:center;gap:8px;margin-top:9px}.provider-footer code{color:var(--muted);font:10.5px var(--mono)}.provider-footer button{padding:4px 9px;border:1px solid var(--line);border-radius:7px;background:#fff;font-size:11px}.provider-footer .link-button{margin-left:auto;border:0;color:var(--blue)}.model-chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:10px}.model-chips span{padding:1px 7px;border-radius:4px;background:#e4edfd;color:var(--blue);font:10.5px var(--mono)}.add-provider{display:flex;align-items:center;gap:9px;width:100%;padding:11px 13px;border:1px dashed rgba(0,0,0,.16);border-radius:10px;text-align:left;color:#61666b}.add-provider small{margin-left:auto;color:var(--faint);font:10.5px var(--mono)}.toml-toolbar{display:flex;align-items:center;gap:6px;margin-bottom:10px;color:var(--muted);font-size:11.5px}.toml-toolbar span{flex:1}.toml-toolbar button{padding:4px 9px;border:1px solid var(--line);border-radius:7px;background:#fff;font-size:11px}.toml-toolbar button.active{background:#f1f3f5;font-weight:600}.toml-toolbar .primary{background:var(--ink);color:#fff}.toml{min-height:420px;border:1px solid var(--line);border-radius:9px;color:#61666b}.command-palette{background:rgba(0,0,0,.18)}.palette-dialog{width:100%;max-width:600px;overflow:hidden;border:1px solid rgba(0,0,0,.12);border-radius:12px;background:#fff;box-shadow:0 24px 64px rgba(0,0,0,.22)}.palette-dialog>input{width:100%;padding:12px 14px;border:0;border-bottom:1px solid var(--line);outline:0}.palette-group{padding:8px}.palette-group small{display:block;padding:4px 6px;color:var(--faint);font:10px var(--mono)}.palette-group button{display:flex;width:100%;padding:9px 7px;text-align:left;font:12px var(--mono)}.palette-group button span{margin-left:16px;color:var(--muted);font:12px var(--sans)}@keyframes pulse{50%{opacity:.3}}@media(max-width:1100px){.details-panel{display:none}.details-toggle{display:none}}@media(max-width:760px){.sidebar{width:216px;flex-basis:216px}.main-header{gap:7px;padding:0 10px}.active-heading small{max-width:180px}.composer-wrap,.chat-scroll{padding-left:12px;padding-right:12px}.view-tabs{margin-left:auto}.composer-hint{display:none}}@media(max-width:560px){.sidebar{width:54px;flex-basis:54px}.brand-row{justify-content:center;padding:0}.brand-row strong,.version,.sidebar-actions,.sidebar-scroll,.runtime-cells,.sidebar-footer{display:none}.main-header .active-heading small{display:none}.view-tab{padding:4px 7px}.details-panel{display:none}.composer-tools{justify-content:flex-end}}
2
+ :root{--empty:#9aa0a6}.empty-state{padding:28px 16px;color:var(--muted);text-align:center;font-size:12px}.settings-plugin-row{padding:8px 0;border-bottom:1px solid rgba(0,0,0,.06);font:11.5px var(--mono);color:#61666b}.settings-body>p{color:var(--muted);font-size:12px}.provider-card input{display:block;width:100%;height:28px;margin-top:7px;border:1px solid rgba(0,0,0,.1);border-radius:7px;padding:0 9px;font:11.5px var(--mono)}.stop-button{padding:2px 8px;border:1px solid rgba(236,19,19,.24);border-radius:6px;color:var(--red);font-size:11px}.stop-button:disabled{opacity:.45;cursor:not-allowed}.session-menu-popover{position:absolute;top:34px;right:0;z-index:35;width:224px;border:1px solid rgba(0,0,0,.1);border-radius:10px;background:#fff;box-shadow:0 10px 28px rgba(0,0,0,.14);overflow:hidden}.session-menu{position:relative}.session-action{display:flex;flex-direction:column;gap:1px;width:100%;padding:8px 11px;border-bottom:1px solid rgba(0,0,0,.04);text-align:left}.session-action:hover{background:var(--soft)}.session-action strong{font-size:12px}.session-action small{color:var(--faint);font-size:10px}.plugins-page{display:flex;flex:1;min-height:0;flex-direction:column}.plugin-description{margin:4px 0 0;color:var(--muted);font-size:12px}.plugin-card{display:block}.plugin-card>.plugin-icon{margin-right:9px}
3
+ :root{--starter-border:rgba(0,0,0,.1)}.starter-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;width:100%;margin-top:10px}.starter-card{padding:10px 12px;border:1px solid var(--starter-border);border-radius:10px;background:#fff;text-align:left}.starter-card:hover{border-color:rgba(65,118,230,.4);background:var(--soft)}.starter-card strong,.starter-card small{display:block}.starter-card strong{font-size:12.5px}.starter-card small{margin-top:4px;color:var(--muted);font:10.5px var(--mono)}
4
+ .main-header{position:relative}.context-bar i:nth-child(1){width:44%;background:#c7d6f5}.context-bar i:nth-child(2){width:33%;background:#dce7fb}.context-bar i:nth-child(3){width:23%;background:#edf2fd}.file-summary{margin:-8px 0 12px;color:var(--muted);font:10.5px var(--mono)}.settings-note{display:block;margin-top:10px;color:var(--muted);font-size:11px;line-height:1.5}.extension-list{max-width:900px}.extension-list .empty-state{border:1px dashed rgba(0,0,0,.14);border-radius:10px}.subnav>a{white-space:nowrap}.plugin-card .switch{margin-left:auto}.session-menu-popover[hidden]{display:none}
5
+ :root{--empty:#9aa0a6}.empty-state{padding:28px 16px;color:var(--muted);text-align:center;font-size:12px}.settings-plugin-row{padding:8px 0;border-bottom:1px solid rgba(0,0,0,.06);font:11.5px var(--mono);color:#61666b}.settings-body>p{color:var(--muted);font-size:12px}.provider-card input{display:block;width:100%;height:28px;margin-top:7px;border:1px solid rgba(0,0,0,.1);border-radius:7px;padding:0 9px;font:11.5px var(--mono)}.stop-button{padding:2px 8px;border:1px solid rgba(236,19,19,.24);border-radius:6px;color:var(--red);font-size:11px}.stop-button:disabled{opacity:.45;cursor:not-allowed}.session-menu-popover{position:absolute;top:34px;right:0;z-index:35;width:224px;border:1px solid rgba(0,0,0,.1);border-radius:10px;background:#fff;box-shadow:0 10px 28px rgba(0,0,0,.14);overflow:hidden}.session-menu{position:relative}.session-action{display:flex;flex-direction:column;gap:1px;width:100%;padding:8px 11px;border-bottom:1px solid rgba(0,0,0,.04);text-align:left}.session-action:hover{background:var(--soft)}.session-action strong{font-size:12px}.session-action small{color:var(--faint);font-size:10px}.plugins-page{display:flex;flex:1;min-height:0;flex-direction:column}.plugin-description{margin:4px 0 0;color:var(--muted);font-size:12px}.plugin-card{display:block}.plugin-card>.plugin-icon{margin-right:9px}
6
+ :root{--starter-border:rgba(0,0,0,.1)}.starter-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;width:100%;margin-top:10px}.starter-card{padding:10px 12px;border:1px solid var(--starter-border);border-radius:10px;background:#fff;text-align:left}.starter-card:hover{border-color:rgba(65,118,230,.4);background:var(--soft)}.starter-card strong,.starter-card small{display:block}.starter-card strong{font-size:12.5px}.starter-card strong{font-size:12.5px}.starter-card small{margin-top:4px;color:var(--muted);font:10.5px var(--mono)}
7
+ :root{--empty:#9aa0a6}.timeline-empty{padding:5px 8px;color:var(--faint);font:10px var(--mono)}.timeline-turn{flex:1;min-width:4px}.timeline-strip{height:100%;background:var(--blue);border-radius:3px}.timeline-turn:nth-child(3n) .timeline-strip{background:#93c5fd}.timeline-turn:nth-child(4n) .timeline-strip{background:#f59e0b}.extension-note{margin:0 0 10px;color:#61666b;font-size:12px;line-height:1.6}.extension-table{border:1px solid var(--line);border-radius:10px;overflow:hidden}.extension-row{display:grid;grid-template-columns:148px 1fr 66px;gap:12px;align-items:center;padding:9px 13px;border-bottom:1px solid rgba(0,0,0,.04)}.extension-row:last-child{border-bottom:0}.extension-head{padding-top:7px;padding-bottom:7px;background:var(--soft);color:var(--faint);font:10px var(--mono);letter-spacing:.04em;text-transform:uppercase}.extension-owners{display:flex;flex-wrap:wrap;gap:5px;min-width:0}.extension-owners span{padding:1px 7px;border-radius:4px;background:#e4edfd;color:var(--blue);font:10.5px var(--mono);overflow-wrap:anywhere}.raw-json{overflow:hidden;border:1px solid var(--line);border-radius:8px}.raw-json summary{padding:7px 9px;cursor:pointer;color:var(--muted);font:10.5px var(--mono)}.raw-json-body{margin:0;padding:9px;border-top:1px solid var(--line);white-space:pre-wrap}.detail-actions{display:flex;gap:7px;margin-top:14px}.detail-actions button{padding:5px 9px;border:1px solid var(--line);border-radius:7px;background:#fff;color:#61666b;font-size:11px}.detail-actions button:disabled{cursor:not-allowed;opacity:.5}
@@ -0,0 +1 @@
1
+ {"extends":"../../tsconfig.build.json","compilerOptions":{"outDir":"server-dist","paths":{},"rootDir":"src/server","lib":["ES2023","DOM","DOM.Iterable"]},"include":["src/server/**/*.ts"]}
@@ -0,0 +1 @@
1
+ {"extends":"../../tsconfig.json","compilerOptions":{"paths":{},"lib":["ES2023","DOM","DOM.Iterable"]},"include":["src/**/*.ts"]}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "pi-harness-workspace",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "workspaces": [
6
+ "packages/*",
7
+ "apps/*",
8
+ "examples/*"
9
+ ],
10
+ "engines": {
11
+ "node": ">=22.19.0"
12
+ },
13
+ "bin": {
14
+ "pih": "./packages/cli/dist/bin.js",
15
+ "pi-harness": "./apps/web/server-dist/bin.js"
16
+ },
17
+ "files": [
18
+ "apps/web",
19
+ "packages"
20
+ ],
21
+ "scripts": {
22
+ "build": "npm run build -w @pi-harness/core && npm run build -w @pi-harness/plugin-hello && npm run build -w @pi-harness/cli && npm run build -w @pi-harness/host-webserver && npm run build -w @pi-harness/api-gateway && npm run build -w @pi-harness/client-web && npm run build -w @pi-harness/web-app && npm run build -w @pi-harness/web",
23
+ "build:web": "npm run build -w @pi-harness/core && npm run build -w @pi-harness/host-webserver && npm run build -w @pi-harness/api-gateway && npm run build -w @pi-harness/client-web && npm run build -w @pi-harness/web-app && npm run build -w @pi-harness/web",
24
+ "web": "npm run build:web && node apps/web/server-dist/bin.js",
25
+ "prepack": "npm run build:web",
26
+ "clean": "npm run clean --workspaces --if-present",
27
+ "lint": "eslint .",
28
+ "test": "npm run build && vitest run",
29
+ "typecheck": "npm run typecheck -w @pi-harness/core && npm run typecheck -w @pi-harness/plugin-hello && npm run typecheck -w @pi-harness/cli && npm run typecheck -w @pi-harness/host-webserver && npm run typecheck -w @pi-harness/api-gateway && npm run typecheck -w @pi-harness/client-web && npm run typecheck -w @pi-harness/web-app && npm run typecheck -w @pi-harness/web"
30
+ },
31
+ "devDependencies": {
32
+ "@eslint/js": "10.0.1",
33
+ "@types/node": "22.19.19",
34
+ "@types/react": "^19.1.10",
35
+ "@types/react-dom": "^19.1.7",
36
+ "eslint": "10.9.1",
37
+ "typescript": "5.9.3",
38
+ "typescript-eslint": "8.68.0",
39
+ "vitest": "4.1.9"
40
+ }
41
+ }
@@ -0,0 +1,8 @@
1
+ import type { Context } from "@deepseek-ai/cordis";
2
+ declare const _default: {
3
+ name: string;
4
+ inject: string[];
5
+ apply(context: Context): void;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;;;;mBAqHlC,OAAO;;AAHxB,wBA0cE"}