nexus-agentd 0.2.2 → 0.2.5

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.
@@ -1,3 +1,4 @@
1
1
  import type { ServerResponse } from 'node:http';
2
2
  export declare function redirectToAgentdWebUi(response: ServerResponse): void;
3
3
  export declare function writeAgentdWebUi(response: ServerResponse): void;
4
+ export declare function writeAgentdWebUiModule(response: ServerResponse, pathname: string): void;
@@ -1,17 +1,23 @@
1
- import { app } from './app.js';
2
1
  import { markup } from './markup.js';
3
2
  import { styles } from './styles.js';
4
- const page = `<!doctype html>
5
- <html lang="zh-CN">
6
- <head>
7
- <meta charset="utf-8">
8
- <meta name="viewport" content="width=device-width, initial-scale=1">
9
- <meta name="color-scheme" content="light dark">
10
- <title>Agent Nexus</title>
11
- <style>${styles}</style>
12
- </head>
13
- <body>${markup}<script>${app}</script></body>
3
+ import { sources } from './app/sources.js';
4
+ const page = `<!doctype html>
5
+ <html lang="zh-CN">
6
+ <head>
7
+ <meta charset="utf-8">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1">
9
+ <meta name="color-scheme" content="light dark">
10
+ <title>Agent Nexus</title>
11
+ <style>${styles}</style>
12
+ <script type="module" defer src="/ui/app.js"></script>
13
+ </head>
14
+ <body>${markup}</body>
14
15
  </html>`;
16
+ const entryModule = `import './app/main.js'\n`;
17
+ const modules = { '/ui/app.js': entryModule };
18
+ for (const [name, source] of Object.entries(sources)) {
19
+ modules['/ui/app/' + name + '.js'] = source;
20
+ }
15
21
  export function redirectToAgentdWebUi(response) {
16
22
  response.writeHead(302, {
17
23
  Location: '/ui/',
@@ -26,7 +32,21 @@ export function writeAgentdWebUi(response) {
26
32
  'Cache-Control': 'no-store',
27
33
  'X-Content-Type-Options': 'nosniff',
28
34
  'Referrer-Policy': 'no-referrer',
29
- 'Content-Security-Policy': "default-src 'none'; connect-src 'self'; img-src 'self' data:; media-src 'self' data:; style-src 'unsafe-inline'; script-src 'unsafe-inline'; base-uri 'none'; frame-ancestors 'none'; form-action 'self'"
35
+ 'Content-Security-Policy': "default-src 'none'; connect-src 'self'; img-src 'self' data:; media-src 'self' data:; style-src 'unsafe-inline'; script-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action 'self'"
30
36
  });
31
37
  response.end(page);
32
38
  }
39
+ export function writeAgentdWebUiModule(response, pathname) {
40
+ const source = modules[pathname];
41
+ if (!source) {
42
+ response.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8', 'Cache-Control': 'no-store' });
43
+ response.end('Not found');
44
+ return;
45
+ }
46
+ response.writeHead(200, {
47
+ 'Content-Type': 'text/javascript; charset=utf-8',
48
+ 'Cache-Control': 'no-store',
49
+ 'X-Content-Type-Options': 'nosniff'
50
+ });
51
+ response.end(source);
52
+ }
@@ -2,30 +2,27 @@ import { icons } from './icons.js';
2
2
  export const markup = String.raw `
3
3
  <div id="setup-screen" class="auth-screen hidden">
4
4
  <form id="setup-form" class="auth-card">
5
- <div class="brand-mark">N</div>
6
- <h1>初始化 Agent Nexus</h1>
7
- <p>创建仅用于后台管理的控制台密码。客户端 API 密钥将在登录后单独管理。</p>
8
- <label>控制台密码<input name="password" type="password" minlength="12" autocomplete="new-password" required></label>
9
- <label>确认密码<input name="confirmPassword" type="password" minlength="12" autocomplete="new-password" required></label>
10
- <button class="button primary" type="submit">完成初始化</button>
5
+ <header><span class="brand-mark">N</span><h1>初始化 Agent Nexus</h1></header>
6
+ <p>此密码仅用于登录控制台;客户端 API 密钥在登录后单独创建。</p>
7
+ <div class="field"><label for="setup-password">控制台密码</label><input id="setup-password" name="password" type="password" minlength="12" autocomplete="new-password" required></div>
8
+ <div class="field"><label for="setup-confirm">确认密码</label><input id="setup-confirm" name="confirmPassword" type="password" minlength="12" autocomplete="new-password" required></div>
9
+ <button class="button primary auth-submit" type="submit">完成初始化</button>
11
10
  <p class="form-error" data-form-error></p>
12
11
  </form>
13
12
  </div>
14
13
 
15
14
  <div id="login-screen" class="auth-screen hidden">
16
15
  <form id="login-form" class="auth-card">
17
- <div class="brand-mark">N</div>
18
- <h1>Agent Nexus</h1>
19
- <p>登录后管理智能体、工作区和客户端 API 密钥。</p>
20
- <label>控制台密码<input name="password" type="password" autocomplete="current-password" required autofocus></label>
21
- <button class="button primary" type="submit">登录</button>
16
+ <header><span class="brand-mark">N</span><h1>Agent Nexus</h1></header>
17
+ <div class="field"><label for="login-password">控制台密码</label><input id="login-password" name="password" type="password" autocomplete="current-password" required autofocus></div>
18
+ <button class="button primary auth-submit" type="submit">登录</button>
22
19
  <p class="form-error" data-form-error></p>
23
20
  </form>
24
21
  </div>
25
22
 
26
23
  <div id="app" class="app-shell hidden">
27
24
  <aside class="sidebar">
28
- <div class="brand"><span class="brand-mark small">N</span><span>Agent Nexus</span></div>
25
+ <div class="brand"><span class="brand-mark">N</span><span>Agent Nexus</span></div>
29
26
  <nav aria-label="主导航">
30
27
  <button class="nav-item active" data-page="overview">${icons.overview}<span>总览</span></button>
31
28
  <button class="nav-item" data-page="runs">${icons.runs}<span>运行记录</span></button>
@@ -36,22 +33,25 @@ export const markup = String.raw `
36
33
  </nav>
37
34
  <div class="admin-menu-wrap">
38
35
  <div id="admin-popover" class="admin-popover hidden">
39
- <label>界面主题
36
+ <div class="field"><label for="theme-select">界面主题</label>
40
37
  <select id="theme-select">
41
38
  <option value="system">跟随系统</option>
42
39
  <option value="light">浅色</option>
43
40
  <option value="dark">深色</option>
44
41
  </select>
45
- </label>
42
+ </div>
46
43
  <button id="change-password" class="menu-button">修改密码</button>
47
44
  <button id="logout" class="menu-button danger-text">退出登录</button>
48
45
  </div>
49
- <button id="admin-menu" class="admin-button" aria-expanded="false">${icons.settings}<span><strong>管理员</strong><small>控制台设置</small></span></button>
46
+ <button id="admin-menu" class="admin-button" aria-expanded="false">
47
+ <span class="avatar">A</span>
48
+ <span class="admin-meta"><strong>管理员</strong></span>
49
+ </button>
50
50
  </div>
51
51
  </aside>
52
52
  <main class="main">
53
- <header class="page-header">
54
- <div><h1 id="page-title"></h1><p id="page-description"></p></div>
53
+ <header class="topbar">
54
+ <h1 id="page-title"></h1>
55
55
  <div id="page-actions" class="page-actions"></div>
56
56
  </header>
57
57
  <section id="page-content" class="page-content" aria-live="polite"></section>
@@ -60,8 +60,9 @@ export const markup = String.raw `
60
60
 
61
61
  <div id="drawer-backdrop" class="drawer-backdrop hidden"></div>
62
62
  <aside id="drawer" class="drawer hidden" aria-modal="true" role="dialog">
63
- <div class="drawer-header"><h2 id="drawer-title"></h2><button id="drawer-close" class="icon-button" aria-label="关闭">×</button></div>
63
+ <div class="drawer-header"><h2 id="drawer-title"></h2><button id="drawer-close" class="icon-button" aria-label="关闭">${icons.close}</button></div>
64
64
  <form id="drawer-form" class="drawer-body"></form>
65
+ <div id="drawer-footer" class="drawer-footer"></div>
65
66
  </aside>
66
67
  <div id="toast-region" class="toast-region" aria-live="assertive"></div>
67
68
  `;