@jasonews/agent-squad-gateway 1.0.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 (149) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +200 -0
  3. package/SECURITY.md +44 -0
  4. package/dist/bin/agent-squad-gateway.js +55 -0
  5. package/dist/bin/agent-squad-gateway.js.map +1 -0
  6. package/dist/config/config.js +124 -0
  7. package/dist/config/config.js.map +1 -0
  8. package/dist/config/paths.js +16 -0
  9. package/dist/config/paths.js.map +1 -0
  10. package/dist/control-plane/clients.js +77 -0
  11. package/dist/control-plane/clients.js.map +1 -0
  12. package/dist/control-plane/core-connection.js +54 -0
  13. package/dist/control-plane/core-connection.js.map +1 -0
  14. package/dist/control-plane/credentials.js +134 -0
  15. package/dist/control-plane/credentials.js.map +1 -0
  16. package/dist/control-plane/db.js +33 -0
  17. package/dist/control-plane/db.js.map +1 -0
  18. package/dist/control-plane/extensions.js +59 -0
  19. package/dist/control-plane/extensions.js.map +1 -0
  20. package/dist/control-plane/grants.js +107 -0
  21. package/dist/control-plane/grants.js.map +1 -0
  22. package/dist/control-plane/idempotency.js +132 -0
  23. package/dist/control-plane/idempotency.js.map +1 -0
  24. package/dist/control-plane/migrations.js +133 -0
  25. package/dist/control-plane/migrations.js.map +1 -0
  26. package/dist/control-plane/response-sessions.js +359 -0
  27. package/dist/control-plane/response-sessions.js.map +1 -0
  28. package/dist/control-plane/retention.js +138 -0
  29. package/dist/control-plane/retention.js.map +1 -0
  30. package/dist/control-plane/runs.js +156 -0
  31. package/dist/control-plane/runs.js.map +1 -0
  32. package/dist/control-plane/targets.js +449 -0
  33. package/dist/control-plane/targets.js.map +1 -0
  34. package/dist/control-plane/types.js +2 -0
  35. package/dist/control-plane/types.js.map +1 -0
  36. package/dist/core-client/client.js +275 -0
  37. package/dist/core-client/client.js.map +1 -0
  38. package/dist/core-client/event-proxy.js +105 -0
  39. package/dist/core-client/event-proxy.js.map +1 -0
  40. package/dist/core-client/types.js +2 -0
  41. package/dist/core-client/types.js.map +1 -0
  42. package/dist/extensions/contract.js +2 -0
  43. package/dist/extensions/contract.js.map +1 -0
  44. package/dist/extensions/openai/auth.js +16 -0
  45. package/dist/extensions/openai/auth.js.map +1 -0
  46. package/dist/extensions/openai/chat.js +403 -0
  47. package/dist/extensions/openai/chat.js.map +1 -0
  48. package/dist/extensions/openai/errors.js +79 -0
  49. package/dist/extensions/openai/errors.js.map +1 -0
  50. package/dist/extensions/openai/image-input.js +79 -0
  51. package/dist/extensions/openai/image-input.js.map +1 -0
  52. package/dist/extensions/openai/models.js +40 -0
  53. package/dist/extensions/openai/models.js.map +1 -0
  54. package/dist/extensions/openai/responses.js +731 -0
  55. package/dist/extensions/openai/responses.js.map +1 -0
  56. package/dist/extensions/openai/routes.js +81 -0
  57. package/dist/extensions/openai/routes.js.map +1 -0
  58. package/dist/extensions/openai/run-attempt.js +96 -0
  59. package/dist/extensions/openai/run-attempt.js.map +1 -0
  60. package/dist/extensions/openai/schemas.js +176 -0
  61. package/dist/extensions/openai/schemas.js.map +1 -0
  62. package/dist/extensions/openai/sse.js +421 -0
  63. package/dist/extensions/openai/sse.js.map +1 -0
  64. package/dist/extensions/openai/tools.js +727 -0
  65. package/dist/extensions/openai/tools.js.map +1 -0
  66. package/dist/extensions/registry.js +30 -0
  67. package/dist/extensions/registry.js.map +1 -0
  68. package/dist/lifecycle/daemon.js +437 -0
  69. package/dist/lifecycle/daemon.js.map +1 -0
  70. package/dist/lifecycle/pidfile.js +34 -0
  71. package/dist/lifecycle/pidfile.js.map +1 -0
  72. package/dist/provider-runtime/antigravity/adapter.js +398 -0
  73. package/dist/provider-runtime/antigravity/adapter.js.map +1 -0
  74. package/dist/provider-runtime/antigravity/conversation.js +31 -0
  75. package/dist/provider-runtime/antigravity/conversation.js.map +1 -0
  76. package/dist/provider-runtime/capability-service.js +191 -0
  77. package/dist/provider-runtime/capability-service.js.map +1 -0
  78. package/dist/provider-runtime/claude/adapter.js +397 -0
  79. package/dist/provider-runtime/claude/adapter.js.map +1 -0
  80. package/dist/provider-runtime/claude/protocol.js +143 -0
  81. package/dist/provider-runtime/claude/protocol.js.map +1 -0
  82. package/dist/provider-runtime/codex/adapter.js +440 -0
  83. package/dist/provider-runtime/codex/adapter.js.map +1 -0
  84. package/dist/provider-runtime/codex/json-rpc-client.js +182 -0
  85. package/dist/provider-runtime/codex/json-rpc-client.js.map +1 -0
  86. package/dist/provider-runtime/codex/protocol.js +128 -0
  87. package/dist/provider-runtime/codex/protocol.js.map +1 -0
  88. package/dist/provider-runtime/command-discovery.js +106 -0
  89. package/dist/provider-runtime/command-discovery.js.map +1 -0
  90. package/dist/provider-runtime/cursor/adapter.js +427 -0
  91. package/dist/provider-runtime/cursor/adapter.js.map +1 -0
  92. package/dist/provider-runtime/cursor/protocol.js +81 -0
  93. package/dist/provider-runtime/cursor/protocol.js.map +1 -0
  94. package/dist/provider-runtime/fake/adapter.js +138 -0
  95. package/dist/provider-runtime/fake/adapter.js.map +1 -0
  96. package/dist/provider-runtime/image-assets.js +409 -0
  97. package/dist/provider-runtime/image-assets.js.map +1 -0
  98. package/dist/provider-runtime/image-support.js +5 -0
  99. package/dist/provider-runtime/image-support.js.map +1 -0
  100. package/dist/provider-runtime/invocation-service.js +503 -0
  101. package/dist/provider-runtime/invocation-service.js.map +1 -0
  102. package/dist/provider-runtime/kimi/adapter.js +657 -0
  103. package/dist/provider-runtime/kimi/adapter.js.map +1 -0
  104. package/dist/provider-runtime/opencode/adapter.js +610 -0
  105. package/dist/provider-runtime/opencode/adapter.js.map +1 -0
  106. package/dist/provider-runtime/opencode/server.js +46 -0
  107. package/dist/provider-runtime/opencode/server.js.map +1 -0
  108. package/dist/provider-runtime/process/line-reader.js +49 -0
  109. package/dist/provider-runtime/process/line-reader.js.map +1 -0
  110. package/dist/provider-runtime/process/managed-process.js +151 -0
  111. package/dist/provider-runtime/process/managed-process.js.map +1 -0
  112. package/dist/provider-runtime/provider-input.js +77 -0
  113. package/dist/provider-runtime/provider-input.js.map +1 -0
  114. package/dist/provider-runtime/register-providers.js +26 -0
  115. package/dist/provider-runtime/register-providers.js.map +1 -0
  116. package/dist/provider-runtime/registry.js +35 -0
  117. package/dist/provider-runtime/registry.js.map +1 -0
  118. package/dist/provider-runtime/replay-buffer.js +168 -0
  119. package/dist/provider-runtime/replay-buffer.js.map +1 -0
  120. package/dist/provider-runtime/scheduler.js +155 -0
  121. package/dist/provider-runtime/scheduler.js.map +1 -0
  122. package/dist/provider-runtime/types.js +2 -0
  123. package/dist/provider-runtime/types.js.map +1 -0
  124. package/dist/provider-runtime/workspaces.js +814 -0
  125. package/dist/provider-runtime/workspaces.js.map +1 -0
  126. package/dist/security/admin-auth.js +109 -0
  127. package/dist/security/admin-auth.js.map +1 -0
  128. package/dist/security/crypto.js +52 -0
  129. package/dist/security/crypto.js.map +1 -0
  130. package/dist/security/secret-files.js +33 -0
  131. package/dist/security/secret-files.js.map +1 -0
  132. package/dist/server/admin-routes.js +610 -0
  133. package/dist/server/admin-routes.js.map +1 -0
  134. package/dist/server/app.js +178 -0
  135. package/dist/server/app.js.map +1 -0
  136. package/dist/server/auth-hooks.js +43 -0
  137. package/dist/server/auth-hooks.js.map +1 -0
  138. package/dist/server/core-routes.js +127 -0
  139. package/dist/server/core-routes.js.map +1 -0
  140. package/dist/server/errors.js +19 -0
  141. package/dist/server/errors.js.map +1 -0
  142. package/dist/server/ui-routes.js +77 -0
  143. package/dist/server/ui-routes.js.map +1 -0
  144. package/dist/web/assets/index-BhqNoPpE.js +206 -0
  145. package/dist/web/assets/index-BhqNoPpE.js.map +1 -0
  146. package/dist/web/assets/index-C5nnaBfZ.css +1 -0
  147. package/dist/web/index.html +14 -0
  148. package/package.json +74 -0
  149. package/translations/README.zh-CN.md +175 -0
@@ -0,0 +1 @@
1
+ :root{--bg: #f5f7f8;--surface: #ffffff;--surface-muted: #eef1f2;--text: #172025;--muted: #647078;--border: #d5dbde;--accent: #087f8c;--success: #18794e;--warning: #a15c00;--danger: #c9372c;--radius-control: 4px;--radius-panel: 6px;--sidebar-width: 224px;--topbar-height: 52px;--control-height: 32px;--control-height-large: 36px;--body-size: 14px;--body-line-height: 20px;--page-heading-size: 22px;--page-heading-line-height: 28px}*{box-sizing:border-box;letter-spacing:0}html,body,#root{min-width:320px;min-height:100%;margin:0}body{min-height:100vh;background:var(--bg);color:var(--text);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:var(--body-size);line-height:var(--body-line-height)}button,a,select,input,textarea{font:inherit}button:focus-visible,a:focus-visible,select:focus-visible{outline:2px solid var(--accent);outline-offset:2px}button{min-height:var(--control-height);border:1px solid var(--border);border-radius:var(--radius-control);background:var(--surface);color:var(--text)}select{height:var(--control-height);border:1px solid var(--border);border-radius:var(--radius-control);background:var(--surface);color:var(--text);padding:0 28px 0 9px}input:not([type=checkbox]){width:100%;height:var(--control-height);border:1px solid var(--border);border-radius:var(--radius-control);background:var(--surface);color:var(--text);padding:0 9px}input:focus-visible{outline:2px solid var(--accent);outline-offset:2px}textarea{width:100%;resize:vertical;border:1px solid var(--border);border-radius:var(--radius-control);background:var(--surface);color:var(--text);padding:8px 9px;font:inherit}textarea:focus-visible{outline:2px solid var(--accent);outline-offset:2px}button:disabled{background:var(--surface-muted);color:var(--muted);cursor:not-allowed}.toggle-control{display:inline-flex;min-width:36px;min-height:28px;align-items:center;gap:8px;border:0;padding:4px 0;background:transparent;color:var(--text);cursor:pointer}.toggle-control:hover:not(:disabled) .toggle-control__track{border-color:var(--accent)}.toggle-control:disabled{background:transparent;color:var(--muted);cursor:not-allowed;opacity:.62}.toggle-control__track{position:relative;width:36px;height:20px;flex:0 0 36px;border:1px solid var(--border);border-radius:999px;background:var(--surface-muted)}.toggle-control__thumb{position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:var(--muted);transition:transform .14s ease}.toggle-control[aria-checked=true] .toggle-control__track{border-color:var(--accent);background:var(--accent)}.toggle-control[aria-checked=true] .toggle-control__thumb{background:var(--surface);transform:translate(16px)}.toggle-control--labelled{min-width:0}.toggle-control__label{text-align:left}.gateway-mark{display:inline-grid;width:28px;height:28px;flex:0 0 28px;place-items:center;border-radius:var(--radius-control);background:var(--accent);color:var(--surface);font-size:15px;font-weight:700;line-height:1}.session-state{display:grid;min-height:100vh;place-items:center;padding:24px}.session-state__panel{width:min(100%,340px);padding:24px;border:1px solid var(--border);border-radius:var(--radius-panel);background:var(--surface);text-align:center}.session-state__panel .gateway-mark{margin:0 auto 12px}.session-state__panel h1{margin:0;font-size:20px;line-height:28px}.session-state__panel p{margin:4px 0 16px;color:var(--muted)}.session-state__panel button{width:100%;min-height:var(--control-height-large);padding:7px 12px}.app-shell{display:grid;min-height:100vh;grid-template-columns:var(--sidebar-width) minmax(0,1fr)}.sidebar{position:fixed;z-index:30;inset:0 auto 0 0;width:var(--sidebar-width);min-width:0;border-right:1px solid var(--border);background:var(--surface);padding:12px;overflow-y:auto}.identity{display:flex;min-height:40px;align-items:center;gap:10px;padding:0 8px 12px;border-bottom:1px solid var(--border);font-size:15px;font-weight:650}.identity>span:nth-child(2){flex:1}.nav-list{display:grid;gap:2px;padding-top:10px}.nav-item{display:flex;height:var(--control-height);align-items:center;gap:9px;padding:0 10px;border-radius:var(--radius-control);color:var(--muted);text-decoration:none}.nav-item:hover:not(.nav-item--disabled){background:var(--surface-muted);color:var(--text)}.nav-item--active{background:var(--surface-muted);color:var(--text);font-weight:600}.nav-item--active svg{color:var(--accent)}.nav-item--disabled{color:color-mix(in srgb,var(--muted) 62%,var(--surface));cursor:not-allowed}.nav-item--degraded{color:var(--warning)}.nav-status-dot{width:6px;height:6px;margin-left:auto;border-radius:50%;background:var(--warning)}.workspace{grid-column:2;min-width:0}.topbar{position:sticky;z-index:20;top:0;height:var(--topbar-height);border-bottom:1px solid var(--border);background:var(--surface)}.topbar__content{display:flex;width:min(100%,1440px);height:100%;align-items:center;justify-content:space-between;margin-inline:auto;padding:0 28px}.topbar__leading{display:flex;align-items:center;gap:10px}.topbar__actions{display:flex;align-items:center;gap:8px}.language-select{display:inline-flex;height:32px;align-items:center;gap:6px;padding:0 7px;border:1px solid var(--border);border-radius:6px;background:var(--surface);color:var(--muted)}.language-select:focus-within{border-color:var(--accent);outline:2px solid color-mix(in srgb,var(--accent) 20%,transparent);outline-offset:1px}.language-select select{width:auto;min-width:72px;height:30px;min-height:30px;padding:0 20px 0 0;border:0;outline:0;background-color:transparent;color:var(--text);font-size:12px}.connection-status{display:inline-flex;align-items:center;gap:8px;color:var(--muted);font-variant-numeric:tabular-nums}.status-dot{width:7px;height:7px;border-radius:50%;background:var(--success)}.core-event-status{display:inline-flex;align-items:center;gap:6px;color:var(--muted);font-size:12px}.core-event-status:before{width:6px;height:6px;border-radius:50%;background:currentColor;content:""}.core-event-status--connected{color:var(--success)}.core-event-status--reconnecting{color:var(--warning)}.core-event-status--offline{color:var(--danger)}.icon-button{display:inline-grid;width:var(--control-height);height:var(--control-height);min-height:var(--control-height);place-items:center;padding:0;cursor:pointer}.icon-button:hover{border-color:var(--muted);background:var(--surface-muted)}.menu-button,.drawer-close,.drawer-backdrop{display:none}.page{width:min(100%,1440px);margin-inline:auto;padding:24px 28px}.page-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;padding-bottom:18px;border-bottom:1px solid var(--border)}.page-heading h1{margin:0;font-size:var(--page-heading-size);line-height:var(--page-heading-line-height)}.page-heading p{margin:2px 0 0;color:var(--muted)}.record-count{color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}.metric-band{display:grid;grid-template-columns:repeat(4,minmax(140px,1fr));margin-top:20px;border-top:1px solid var(--border);border-bottom:1px solid var(--border);background:var(--surface)}.metric-cell{display:grid;gap:2px;min-height:88px;align-content:center;padding:14px 18px}.metric-cell+.metric-cell{border-left:1px solid var(--border)}.metric-cell>span,.metric-cell small{color:var(--muted);font-size:12px;line-height:16px}.metric-cell strong{font-weight:600;font-variant-numeric:tabular-nums}.metric-value{font-size:20px;line-height:24px}.semantic-status{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:650;line-height:18px;text-transform:capitalize}.semantic-status:before{width:6px;height:6px;border-radius:50%;background:currentColor;content:""}.semantic-status--success{color:var(--success)}.semantic-status--warning{color:var(--warning)}.semantic-status--danger{color:var(--danger)}.semantic-status--accent{color:var(--accent)}.semantic-status--muted{color:var(--muted)}.operations-section,.table-section{margin-top:26px}.section-heading{display:flex;min-height:34px;align-items:center;justify-content:space-between;gap:16px;border-bottom:1px solid var(--border);padding-bottom:8px}.section-heading h2{margin:0;font-size:15px;line-height:22px}.section-heading span,.section-heading a{color:var(--muted);font-size:12px}.pressure-list{background:var(--surface)}.pressure-row{display:grid;min-height:36px;grid-template-columns:minmax(180px,1fr) 90px 90px;align-items:center;border-bottom:1px solid var(--border);padding:0 12px;font-variant-numeric:tabular-nums}.pressure-row--header{min-height:32px;background:var(--surface-muted);color:var(--muted);font-size:12px;font-weight:600}.filter-bar{display:grid;grid-template-columns:repeat(4,minmax(150px,220px));gap:12px;margin-top:18px;border-bottom:1px solid var(--border);padding-bottom:18px}.filter-bar label{display:grid;gap:4px;color:var(--muted);font-size:12px}.filter-bar select{width:100%;color:var(--text);font-size:var(--body-size)}.data-table-wrap{width:100%;overflow-x:auto;border-bottom:1px solid var(--border);background:var(--surface)}.data-table{width:100%;min-width:1076px;border-collapse:collapse;table-layout:fixed}.data-table th,.data-table td{height:38px;border-bottom:1px solid var(--border);padding:0 10px;overflow:hidden;text-align:left;text-overflow:ellipsis;white-space:nowrap}.data-table th{height:34px;background:var(--surface-muted);color:var(--muted);font-size:12px;font-weight:650}.data-table tbody tr:hover{background:color-mix(in srgb,var(--accent) 4%,var(--surface))}.data-table tbody tr:last-child td{border-bottom:0}.numeric{font-variant-numeric:tabular-nums}.code-cell{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.actions-cell{text-align:center!important}.button{display:inline-flex;min-height:var(--control-height);align-items:center;justify-content:center;gap:7px;padding:0 11px;cursor:pointer}.button.icon-button{padding:0}.button.menu-button,.button.drawer-close{display:none}.button--danger{border-color:var(--danger);background:var(--danger);color:var(--surface)}.button--quiet{background:transparent}.empty-state{display:grid;min-height:76px;place-content:center;gap:2px;color:var(--muted);text-align:center}.empty-state strong{color:var(--text);font-weight:600}.dialog-layer{position:fixed;z-index:50;top:0;right:0;bottom:0;left:0;display:grid;place-items:center;padding:20px;background:#1720255c}.dialog{width:min(100%,420px);border:1px solid var(--border);border-radius:var(--radius-panel);background:var(--surface);box-shadow:0 16px 42px #17202533;padding:20px}.dialog--wide{width:min(100%,760px);max-height:calc(100vh - 40px);overflow-y:auto}.target-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 16px}.field,.field label{display:grid;gap:4px}.field label>span,.field>small{color:var(--muted);font-size:12px}.field__label--required:after{content:" (required)"}.field__label--optional:after{content:" (optional)"}html[lang=zh-CN] .field__label--required:after{content:"(必填)"}html[lang=zh-CN] .field__label--optional:after{content:"(可选)"}.field select{width:100%}.target-validation{margin:12px 0 0;font-size:13px}.acknowledgements{display:grid;gap:8px;margin-top:16px;border-top:1px solid var(--border);padding-top:12px}.acknowledgements label{display:flex;align-items:center;gap:8px}.table-actions{display:flex;align-items:center;justify-content:center;gap:4px}.dialog h2{margin:0 0 16px;font-size:17px;line-height:24px}.dialog-facts{margin:0;border-top:1px solid var(--border)}.dialog-facts div{display:grid;grid-template-columns:72px minmax(0,1fr);border-bottom:1px solid var(--border);padding:8px 0}.dialog-facts dt{color:var(--muted)}.dialog-facts dd{margin:0;overflow-wrap:anywhere}.dialog-error{color:var(--danger)}.choice-form{display:grid;gap:16px}.choice-form fieldset{display:grid;gap:8px;margin:0;border:0;padding:0}.choice-form legend{margin-bottom:6px;color:var(--muted);font-size:12px}.choice-option{display:grid;grid-template-columns:18px minmax(0,1fr);align-items:start;gap:8px;border:1px solid var(--border);border-radius:var(--radius-control);padding:10px;cursor:pointer}.choice-option input{width:16px;height:16px;margin:2px 0 0}.choice-option>span,.choice-cell-detail{display:grid;min-width:0}.choice-option small,.choice-cell-detail small,.choice-rationale>span,.choice-rationale>small{color:var(--muted);font-size:12px}.choice-recommendation{display:grid;gap:2px;margin:0;border-left:3px solid var(--accent);padding-left:10px}.choice-recommendation span{color:var(--muted)}.choice-rationale{display:grid;gap:4px}.muted{color:var(--muted)}.client-section{margin-top:26px}.operation-notice{margin:14px 0 0;color:var(--success)}.operation-status{display:flex;align-items:center;gap:7px;margin:12px 0 0;color:var(--accent)}.verification-status{display:flex;align-items:flex-start;gap:9px;margin-top:14px;border-left:3px solid var(--accent);padding:8px 10px;background:var(--surface-muted)}.verification-status>span{display:grid;gap:2px}.verification-status small{color:var(--muted)}.dialog-toggle{margin-top:12px}.icon-spin{animation:icon-spin .9s linear infinite}@keyframes icon-spin{to{transform:rotate(360deg)}}.credential-list{border-bottom:1px solid var(--border);background:var(--surface)}.credential-row{display:grid;min-height:58px;grid-template-columns:minmax(160px,220px) minmax(300px,1fr) 80px;align-items:center;gap:14px;border-bottom:1px solid var(--border);padding:8px 10px}.credential-row:last-child{border-bottom:0}.credential-row>div:first-child{display:grid}.credential-row small,.grant-row small{color:var(--muted)}.secret-field{display:grid;grid-template-columns:minmax(0,1fr) 32px 32px;align-items:center;gap:4px}.secret-field__mask{overflow:hidden;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.secret-field input{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.secret-field__error{grid-column:1 / -1;color:var(--danger);font-size:12px}.grant-matrix{display:grid;gap:18px;padding-top:12px}.grant-group{border-bottom:1px solid var(--border)}.grant-group h3{margin:0;padding:7px 10px;background:var(--surface-muted);font-size:13px}.grant-row{display:grid;width:100%;min-height:46px;grid-template-columns:42px minmax(0,1fr);align-items:center;border-bottom:1px solid var(--border);padding:5px 10px;background:var(--surface);text-align:left}.grant-row>.toggle-control__label{display:grid}.grant-row:disabled{color:var(--text);opacity:1}.grant-row:disabled .toggle-control__track{opacity:.62}.credential-form{display:grid;gap:12px}.settings-section{margin-top:24px}.settings-core-row,.setup-inline{display:grid;grid-template-columns:minmax(240px,1fr) auto auto;align-items:end;gap:10px;padding-top:12px}.definition-list{margin:0}.definition-list>div{display:grid;grid-template-columns:180px minmax(0,1fr);min-height:38px;align-items:center;border-bottom:1px solid var(--border)}.definition-list dt{color:var(--muted)}.definition-list dd{margin:0;overflow-wrap:anywhere;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.setup-steps{margin-top:8px}.setup-step{display:grid;grid-template-columns:36px minmax(0,1fr);gap:12px;border-bottom:1px solid var(--border);padding:16px 0}.setup-step__index{display:grid;width:30px;height:30px;place-items:center;border:1px solid var(--border);border-radius:var(--radius-control);color:var(--accent)}.setup-step__body{min-width:0}.setup-actions{display:flex;align-items:center;gap:10px;padding-top:12px}.setup-actions>span{color:var(--muted);font-size:12px}.suggestion-list{display:grid;margin:10px 0;border-top:1px solid var(--border)}.suggestion-row{display:grid;width:100%;min-height:46px;grid-template-columns:42px minmax(0,1fr);align-items:center;border-bottom:1px solid var(--border);text-align:left}.suggestion-row>.toggle-control__label{display:grid}.suggestion-list small{color:var(--muted)}.setup-finish{display:flex;justify-content:flex-end;padding-top:16px}@media(max-width:680px){.settings-core-row,.setup-inline{grid-template-columns:1fr;align-items:stretch}.definition-list>div{grid-template-columns:1fr;gap:2px;padding:7px 0}}.core-detail-heading code,.native-session code{overflow-wrap:anywhere;white-space:normal}.core-back-link{display:inline-block;margin-bottom:4px;color:var(--accent);font-size:12px}.core-tabs{display:flex;gap:2px;margin-top:18px;border-bottom:1px solid var(--border)}.core-tabs button{min-width:112px;border-color:transparent;border-bottom:2px solid transparent;border-radius:0;background:transparent}.core-tabs button[aria-selected=true]{border-bottom-color:var(--accent);color:var(--accent)}.core-detail-grid{display:grid;grid-template-columns:minmax(0,1fr) 360px;gap:20px;margin-top:14px}.core-panel{min-width:0;border-top:1px solid var(--border);background:var(--surface)}.core-panel__title{margin:0;border-bottom:1px solid var(--border);padding:10px 12px;background:var(--surface-muted);font-size:13px}.core-message,.core-subagent,.core-choice{min-width:0;border-bottom:1px solid var(--border);padding:12px}.core-message__meta,.core-subagent__heading,.core-choice__heading{display:flex;min-width:0;align-items:center;justify-content:space-between;gap:10px;color:var(--muted);font-size:12px}.core-message__meta strong,.core-subagent__heading strong,.core-choice__heading strong{color:var(--text)}.core-message p,.core-choice p{margin:8px 0 0;overflow-wrap:anywhere;white-space:pre-wrap}.core-facts{margin:10px 0}.core-facts>div{display:grid;grid-template-columns:96px minmax(0,1fr);gap:8px;padding:3px 0}.core-facts dt{color:var(--muted)}.core-facts dd{min-width:0;margin:0;overflow-wrap:anywhere}.core-choice__facts{margin:10px 0 0}.core-choice__facts>div{display:grid;grid-template-columns:72px minmax(0,1fr);gap:8px;padding:3px 0}.core-choice__facts dt{color:var(--muted)}.core-choice__facts dd{min-width:0;margin:0;overflow-wrap:anywhere}.native-session{display:flex;min-width:0;align-items:center;gap:4px}.native-session code{min-width:0;flex:1}.core-empty{padding:12px;color:var(--muted)}.dialog--wide:has(.raw-tail){display:grid;grid-template-rows:auto minmax(0,1fr) auto;overflow:hidden}.raw-tail{min-height:0;overflow:auto}.raw-tail__content{min-height:240px;max-height:60vh;margin:0;overflow:auto;padding:12px;background:var(--surface-muted);font:12px/18px ui-monospace,SFMono-Regular,Menlo,monospace;overflow-wrap:anywhere;white-space:pre-wrap}.raw-tail__empty{min-height:160px;margin:0;display:grid;place-content:center;color:var(--muted)}.core-unavailable{max-width:520px}.core-unavailable h1{font-size:var(--page-heading-size)}.core-unavailable{margin-top:24px}.core-session-link{color:var(--accent);font-weight:600}.data-table td.core-wrap-cell{overflow-wrap:anywhere;white-space:normal}@media(max-width:760px){.credential-row{grid-template-columns:minmax(0,1fr)}.secret-field{width:100%}}@media(max-width:959px){.core-detail-grid{grid-template-columns:minmax(0,1fr)}}@media(max-width:420px){.connection-status,.core-event-status{display:none}}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:18px}.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media(prefers-reduced-motion:reduce){.toggle-control__thumb{transition:none}.icon-spin{animation:none}}@media(max-width:759px){.app-shell{grid-template-columns:1fr}.sidebar{transform:translate(-100%);visibility:hidden;transition:transform .16s ease;box-shadow:12px 0 32px #1720252e}.sidebar--open{transform:translate(0);visibility:visible}.workspace{grid-column:1}.button.menu-button,.button.drawer-close{display:inline-grid}.drawer-backdrop{position:fixed;z-index:25;top:0;right:0;bottom:0;left:0;display:block;width:100%;height:100%;min-height:0;border:0;border-radius:0;background:#17202547;padding:0}.page{padding:20px 16px}.topbar__content{padding-inline:16px}.metric-band{grid-template-columns:1fr}.metric-cell+.metric-cell{border-top:1px solid var(--border);border-left:0}.filter-bar,.target-form{grid-template-columns:1fr}.pressure-row{grid-template-columns:minmax(120px,1fr) 64px 64px}}
@@ -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="color-scheme" content="light" />
7
+ <title>Gateway</title>
8
+ <script type="module" crossorigin src="/assets/index-BhqNoPpE.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-C5nnaBfZ.css">
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ </body>
14
+ </html>
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@jasonews/agent-squad-gateway",
3
+ "version": "1.0.0",
4
+ "description": "Local control plane and OpenAI-compatible API gateway for coding CLI models.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/JASONews/agent-squad-gateway.git"
10
+ },
11
+ "homepage": "https://github.com/JASONews/agent-squad-gateway#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/JASONews/agent-squad-gateway/issues"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public",
17
+ "registry": "https://registry.npmjs.org/"
18
+ },
19
+ "bin": {
20
+ "agent-squad-gateway": "./dist/bin/agent-squad-gateway.js"
21
+ },
22
+ "files": [
23
+ "dist/",
24
+ "README.md",
25
+ "translations/",
26
+ "LICENSE",
27
+ "SECURITY.md"
28
+ ],
29
+ "engines": {
30
+ "node": ">=20"
31
+ },
32
+ "scripts": {
33
+ "build": "tsc -p tsconfig.node.json && tsc -p web/tsconfig.json && vite build",
34
+ "prepack": "npm run build",
35
+ "dev": "vite --config vite.config.ts",
36
+ "dev:server": "tsx watch src/bin/agent-squad-gateway.ts start --foreground",
37
+ "test": "vitest run",
38
+ "test:all": "vitest run && playwright test",
39
+ "test:browser": "playwright test",
40
+ "test:real-providers": "GATEWAY_REAL_CLI_TEST=1 vitest run tests/integration/real-providers.test.ts",
41
+ "test:watch": "vitest"
42
+ },
43
+ "dependencies": {
44
+ "@agentclientprotocol/sdk": "^1.2.1",
45
+ "@fastify/static": "^9.1.1",
46
+ "@opencode-ai/sdk": "1.17.15",
47
+ "@tanstack/react-query": "^5.66.0",
48
+ "ajv": "^8.20.0",
49
+ "better-sqlite3": "^11.7.0",
50
+ "commander": "^12.1.0",
51
+ "fastify": "^5.2.0",
52
+ "lucide-react": "^0.468.0",
53
+ "react": "^18.3.1",
54
+ "react-dom": "^18.3.1",
55
+ "zod": "^3.25.0"
56
+ },
57
+ "devDependencies": {
58
+ "@playwright/test": "^1.49.1",
59
+ "@testing-library/jest-dom": "^6.6.3",
60
+ "@testing-library/react": "^16.1.0",
61
+ "@testing-library/user-event": "^14.6.1",
62
+ "@types/better-sqlite3": "^7.6.12",
63
+ "@types/node": "^22.10.0",
64
+ "@types/react": "^18.3.18",
65
+ "@types/react-dom": "^18.3.5",
66
+ "@vitejs/plugin-react": "^4.3.4",
67
+ "jsdom": "^25.0.1",
68
+ "openai": "^6.46.0",
69
+ "tsx": "^4.19.2",
70
+ "typescript": "^5.7.2",
71
+ "vite": "^6.0.7",
72
+ "vitest": "^4.1.10"
73
+ }
74
+ }
@@ -0,0 +1,175 @@
1
+ # Agent Squad Gateway
2
+
3
+ **面向本地编程 CLI 模型的控制平面与 OpenAI 兼容 API Gateway。**
4
+
5
+ [English](https://github.com/JASONews/agent-squad-gateway/blob/main/README.md) | **简体中文**
6
+
7
+ Agent Squad Gateway 将本机已安装并登录的编程 CLI 模型,通过 Web 管理界面和 OpenAI
8
+ 兼容接口提供给 LiteLLM、IDE 或其他 API 客户端。Gateway 负责模型别名、API Key、访问授权、
9
+ 并发控制、流式输出与能力验证;各 CLI 继续使用自己的本地登录状态。
10
+
11
+ Agent Squad Core 是可选且独立的。Gateway 可以读取 Core 会话和待处理选择用于调试,但 Core
12
+ 不依赖 Gateway,Gateway 的 provider runtime 也可以在没有 Core 时独立运行。
13
+
14
+ ```text
15
+ OpenAI 客户端 / LiteLLM / IDE
16
+ |
17
+ /v1 API + SSE
18
+ |
19
+ Agent Squad Gateway + Web UI
20
+ |
21
+ Codex / Claude Code / Cursor Agent / OpenCode / Antigravity / Kimi Code
22
+ ```
23
+
24
+ ## 主要功能
25
+
26
+ - 兼容 `GET /v1/models`、`POST /v1/chat/completions` 和 `POST /v1/responses`。
27
+ - 通过 SSE 返回流式响应;Responses API 可使用 `previous_response_id` 恢复会话。
28
+ - 客户端工具调用:Gateway 返回 tool call,实际函数由 API 客户端执行。
29
+ - 支持在 Web UI 中管理 CLI、调用目标、验证、客户端、可恢复的本地 API Key、授权、运行元数据、
30
+ extension、设置和可选的 Core 调试信息。
31
+ - 每个 target 可配置模型、reasoning effort、隔离级别、流式模式、队列、并发、超时与 workspace。
32
+ - CLI 版本变化后 provider 仍保持 Available,只要求受影响的 target 重新验证。
33
+ - Gateway 数据库只保存元数据,不保存 prompt、completion、tool payload 或 provider 原始事件。
34
+
35
+ ## 环境要求
36
+
37
+ - Node.js 20 或更新版本
38
+ - npm
39
+ - 至少安装并登录一个 provider CLI:
40
+ - Codex:`codex`
41
+ - Claude Code:`claude`
42
+ - Cursor Agent:`cursor-agent`
43
+ - OpenCode:`opencode`
44
+ - Antigravity:`agy`
45
+ - Kimi Code:`kimi`
46
+
47
+ ## 安装
48
+
49
+ ### npm
50
+
51
+ Agent Squad Gateway 已作为公开 package 发布到 npm registry,无需配置 registry token:
52
+
53
+ ```bash
54
+ npm install -g @jasonews/agent-squad-gateway
55
+
56
+ agent-squad-gateway --help
57
+ ```
58
+
59
+ ### 从源码构建
60
+
61
+ ```bash
62
+ git clone https://github.com/JASONews/agent-squad-gateway.git
63
+ cd agent-squad-gateway
64
+ npm ci
65
+ npm run build
66
+ npm link
67
+ ```
68
+
69
+ ## 快速开始
70
+
71
+ ```bash
72
+ agent-squad-gateway start
73
+ agent-squad-gateway open
74
+ ```
75
+
76
+ 默认监听 `0.0.0.0:28772`,因此本地容器可以访问。首次启动会创建
77
+ `~/.agent-squad/gateway/config.json`:
78
+
79
+ ```json
80
+ {
81
+ "address": "0.0.0.0",
82
+ "port": 28772,
83
+ "web_ui_auth": "disabled"
84
+ }
85
+ ```
86
+
87
+ 只允许本机访问时,请把 `address` 改为 `127.0.0.1`。当管理界面可能被不可信网络访问时,
88
+ 请把 `web_ui_auth` 改为 `token`。修改后需要重启 Gateway。
89
+
90
+ 在 Web UI 中依次完成:
91
+
92
+ 1. 扫描本机 CLI。
93
+ 2. 创建并验证 invocation target。验证会真实调用模型,可能消耗额度。
94
+ 3. 启用验证成功的 target。
95
+ 4. 创建 client 和 API Key。
96
+ 5. 启用 OpenAI extension,并授权 client 使用指定 target。
97
+
98
+ ## OpenAI 兼容接口
99
+
100
+ 本机使用 `http://127.0.0.1:28772/v1`;Docker Desktop 容器可使用
101
+ `http://host.docker.internal:28772/v1`。
102
+
103
+ ```bash
104
+ export AGENT_SQUAD_BASE_URL=http://127.0.0.1:28772/v1
105
+ export AGENT_SQUAD_API_KEY=asqsk_your_key
106
+
107
+ curl "$AGENT_SQUAD_BASE_URL/models" \
108
+ -H "Authorization: Bearer $AGENT_SQUAD_API_KEY"
109
+
110
+ curl "$AGENT_SQUAD_BASE_URL/chat/completions" \
111
+ -H "Authorization: Bearer $AGENT_SQUAD_API_KEY" \
112
+ -H "Content-Type: application/json" \
113
+ -d '{
114
+ "model": "codex-gpt56-max",
115
+ "messages": [{"role":"user","content":"解释这个仓库。"}],
116
+ "stream": true
117
+ }'
118
+ ```
119
+
120
+ 请求中的 model 是已启用 target 的 ID 或其 alias。未配置的模型会被拒绝。
121
+
122
+ ## 工具调用边界
123
+
124
+ API tool call 属于客户端:客户端在请求中提交 OpenAI function 定义,执行 Gateway 返回的调用,
125
+ 再在下一轮提交工具结果。Gateway 不会把 provider CLI 的个人工具、MCP server、skill 或 workspace
126
+ 作为 API 工具暴露。
127
+
128
+ ## CLI
129
+
130
+ ```bash
131
+ agent-squad-gateway start [--foreground] [--address ADDRESS] [--port PORT]
132
+ agent-squad-gateway stop
133
+ agent-squad-gateway status
134
+ agent-squad-gateway open
135
+ agent-squad-gateway doctor
136
+ ```
137
+
138
+ 配置优先级从低到高为:内置默认值、`config.json`、环境变量、CLI 参数。支持的环境变量包括:
139
+
140
+ ```bash
141
+ AGENT_SQUAD_GATEWAY_ADDRESS=127.0.0.1
142
+ AGENT_SQUAD_GATEWAY_PORT=28772
143
+ AGENT_SQUAD_GATEWAY_WEB_UI_AUTH=token
144
+ ```
145
+
146
+ ## 本地状态
147
+
148
+ Gateway 状态保存在 `~/.agent-squad/gateway/`。其中 `gateway.db` 保存 target、client、加密凭据、
149
+ 授权和运行元数据;`master.key` 用于解密可恢复的 API Key;`workspaces/` 保存 Gateway 管理的
150
+ provider workspace。API Key 可以在本地管理界面中重新显示,因此必须同时保护 `gateway.db` 和
151
+ `master.key`。
152
+
153
+ ## 安全
154
+
155
+ Gateway 是本地开发基础设施,不是公网服务。不要通过公网路由器或反向代理暴露它。启用局域网或
156
+ 容器访问、使用固定 workspace、或处理敏感内容前,请阅读 [SECURITY.md](../SECURITY.md)。
157
+
158
+ ## 开发与测试
159
+
160
+ ```bash
161
+ npm ci
162
+ npm run build
163
+ npm test
164
+ ```
165
+
166
+ 默认测试使用 fake provider,不会调用真实模型。真实 provider 测试必须显式指定 target,且可能
167
+ 消耗额度:
168
+
169
+ ```bash
170
+ GATEWAY_REAL_TARGETS=target_a,target_b npm run test:real-providers
171
+ ```
172
+
173
+ ## License
174
+
175
+ [MIT](../LICENSE)