local-agent-dashboard 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,14 +1,78 @@
1
- # Agent Signal macOS 服务端
1
+ # Local Agent Dashboard
2
2
 
3
- 需要 macOS 13+、Node >=22.18 和 OpenSSL 3(brew install openssl@3)。
3
+ 把闲置的 Android 手机变成 AI 任务看板:不用一直盯着电脑,也能看到 Codex Desktop 和 Claude Code 是否还在运行、是否需要你处理,以及有没有报错。
4
4
 
5
- 运行:npx local-agent-dashboard;本地归档:npx --package ./包名.tgz local-agent-dashboard。
6
- 启动打开电脑任务总览,“连接手机”中默认预选全部网卡,应用后启用 TLS。手机安装独立 Android APK,App 扫码后在电脑批准。
5
+ 电脑上运行这个 npm 包,手机上安装配套 App。手机和电脑需要连接同一个局域网,也可以在 App 中添加多台电脑。
7
6
 
8
- 数据在 ~/Library/Application Support/Agent Signal;--state-dir 可选已有目录,目录不得多人共用。源码版的 .runtime 不会自动迁移。
9
- 每次重启仍需重新批准手机,当前设备授权未持久化。
7
+ ## 电脑需要什么?
10
8
 
11
- --help 查看参数;--doctor 检查依赖;--demo 仅合成样本;--no-open 不自动打开浏览器。
12
- 初次运行读取本机 Codex/Claude 的任务状态;不更改原生配置,不安装 Hook。
9
+ - macOS 13 或更新版本,支持 Apple 芯片和 Intel 芯片。
10
+ - [Node.js](https://nodejs.org/) 22.18 或更新版本。
11
+ - OpenSSL 3。如果已经安装 [Homebrew](https://brew.sh/),运行:
13
12
 
14
- 个人研究软件,尚未授权再分发;UNLICENSED。
13
+ ```sh
14
+ brew install openssl@3
15
+ ```
16
+
17
+ 目前电脑端仅支持 macOS,暂不支持 Windows 和 Linux。
18
+
19
+ ## 启动电脑端
20
+
21
+ 在终端运行:
22
+
23
+ ```sh
24
+ npx local-agent-dashboard@0.3.3
25
+ ```
26
+
27
+ 第一次运行时,npx 会询问是否下载,输入 `y` 确认即可。启动后会自动打开浏览器,显示这台电脑最近的任务。
28
+
29
+ 使用期间请保持这个终端窗口打开。要停止服务,在终端按 `Control + C`。
30
+
31
+ ## 连接 Android 手机
32
+
33
+ 1. 从 [GitHub 下载 0.3.3 的 Android 安装包](https://github.com/jiahim/local-agent-dashboard/releases/tag/v0.3.3),在手机上安装。请选择 `.apk` 文件;无需安装 Expo Go。
34
+ 2. 让手机和电脑连接同一个 Wi-Fi,或处于可以互相访问的局域网。
35
+ 3. 在电脑页面点击 **连接手机**,确认网络地址,再点击 **应用所选地址**。默认会选中所有可用地址,也可以用全选、反选来调整。
36
+ 4. 点击 **生成配对邀请**。打开手机 App,在 **设置 → 电脑连接** 中扫码;也可以把配对链接发送到手机,点击链接打开 App。
37
+ 5. 核对手机显示的电脑身份,并在电脑页面确认对应的连接申请。
38
+
39
+ 连接成功后,手机就会显示这台电脑的任务。需要添加其他电脑时,在那些电脑上运行同一个命令,再从手机设置中添加。
40
+
41
+ 手机端仅支持 Android arm64,系统要求 Android 8.0 或更新版本。目前 APK 使用测试签名,供试用。
42
+
43
+ ## 常用命令
44
+
45
+ | 用途 | 命令 |
46
+ | --- | --- |
47
+ | 检查运行环境,排查启动问题 | `npx local-agent-dashboard@0.3.3 --doctor` |
48
+ | 用示例任务体验界面 | `npx local-agent-dashboard@0.3.3 --demo` |
49
+ | 启动时不自动打开浏览器 | `npx local-agent-dashboard@0.3.3 --no-open` |
50
+ | 查看全部参数 | `npx local-agent-dashboard@0.3.3 --help` |
51
+
52
+ 如果下载的是 Release 中的 `.tgz` 文件,在文件所在目录运行:
53
+
54
+ ```sh
55
+ npx --package ./local-agent-dashboard-0.3.3.tgz local-agent-dashboard
56
+ ```
57
+
58
+ ## 数据保存在哪里?
59
+
60
+ 新安装的数据保存在当前用户目录:
61
+
62
+ ```text
63
+ ~/Library/Application Support/Local Agent Dashboard
64
+ ```
65
+
66
+ 如果你已经使用过旧版,且没有创建过新目录,程序会继续使用原来的 `~/Library/Application Support/Agent Signal`,保留已有电脑身份,不会自动移动或删除文件。启动前运行 `--doctor`,可以查看实际使用的目录。
67
+
68
+ 也可以用 `--state-dir <目录>` 指定已有数据目录。同一个目录不要同时运行两个服务。通过源码启动时使用的 `.runtime` 目录不会自动迁移。
69
+
70
+ **目前电脑服务重启后,需要在电脑上重新确认手机连接。** 电脑身份会保留,但已批准的手机连接尚未持久保存。
71
+
72
+ ## 隐私与使用范围
73
+
74
+ 程序只读取本机 Codex 和 Claude Code 的任务状态,不安装 Hook,也不修改它们的配置。电脑管理页面只允许本机访问,手机连接使用加密通信,不经过云端中转。
75
+
76
+ 任务标题可能包含私人信息,请只连接你信任的设备,不要公开分享配对链接或数据目录。任务状态识别仍在完善,部分会话可能显示为状态待确认。
77
+
78
+ 项目目前未提供开源许可证,按 `UNLICENSED` 管理。源码、问题反馈和版本下载见 [GitHub 仓库](https://github.com/jiahim/local-agent-dashboard)。
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "local-agent-dashboard",
3
- "version": "0.3.2",
4
- "description": "Agent Signal macOS LAN host for the Android App",
3
+ "version": "0.3.3",
4
+ "description": "在 Android 手机上查看 Mac 的 Codex 和 Claude Code 任务状态",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/jiahim/local-agent-dashboard.git"
package/public/app.js CHANGED
@@ -97,7 +97,7 @@ function route(){
97
97
  const key=location.hash.slice(1),page=({connect:'connect',setup:'connect',devices:'devices','device-management':'devices'})[key]||'tasks';
98
98
  document.querySelectorAll('[data-route]').forEach(el=>el.hidden=el.dataset.route!==page);
99
99
  document.querySelectorAll('[data-page]').forEach(el=>{if(el.dataset.page===page)el.setAttribute('aria-current','page');else el.removeAttribute('aria-current');});
100
- const title={tasks:'任务总览',connect:'连接手机',devices:'设备管理'}[page];$('page-title').textContent=title;document.title=`Agent Signal · ${title}`;
100
+ const title={tasks:'任务总览',connect:'连接手机',devices:'设备管理'}[page];$('page-title').textContent=title;document.title=`Local Agent Dashboard · ${title}`;
101
101
  }
102
102
  window.addEventListener('hashchange',route);route();
103
103
  $('reset-filters').onclick=()=>{statuses=new Set();filter='all';render();};
package/public/index.html CHANGED
@@ -1,8 +1,8 @@
1
- <!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Agent Signal · 任务总览</title><link rel="stylesheet" href="/style.css"><body>
2
- <header><div><small>AGENT SIGNAL</small><h1 id="page-title">任务总览</h1></div><span id="connection">连接中</span></header>
1
+ <!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Local Agent Dashboard · 任务总览</title><link rel="stylesheet" href="/style.css"><body>
2
+ <header><div><small>LOCAL AGENT DASHBOARD</small><h1 id="page-title">任务总览</h1></div><span id="connection">连接中</span></header>
3
3
  <nav class="management-nav" aria-label="主要导航"><a href="#tasks" data-page="tasks" aria-current="page">任务总览</a><a href="#devices" data-page="devices">设备管理</a><a class="primary" href="#connect" data-page="connect">连接手机</a></nav>
4
4
  <p id="error" role="alert" hidden></p><p id="banner" hidden></p>
5
5
  <main id="tasks-page" data-route="tasks"><p class="intro">这里是手机同步的任务数据。查看最近会话,或筛选需要关注的状态。</p><div id="overview" aria-label="状态筛选"></div><nav id="running-subsets" aria-label="运行中子筛选" hidden></nav><div class="board-toolbar"><nav id="applications" aria-label="来源筛选"></nav><button id="reset-filters">清除状态筛选</button></div><div id="tasks" aria-label="会话列表"></div><p id="empty" class="empty" hidden></p><details class="coverage"><summary>数据来源与覆盖范围</summary><div id="sources"></div></details></main>
6
- <main id="connect-page" data-route="connect" hidden><a class="back" href="#tasks">‹ 返回任务总览</a><div class="connect-grid"><section><h2>连接你的手机</h2><p>在 Agent Signal App 中打开「设置 → 电脑连接 → 扫码连接电脑」,或在手机点击配对链接。</p><button class="primary" id="invite">生成配对邀请</button><div id="qr"></div><div id="invitation-actions" hidden><button id="enlarge-qr">放大二维码</button><button id="copy-pair-link">复制配对链接</button><p id="link-feedback" role="status"></p><a id="pair-link">在手机上打开 App</a><textarea id="pair-link-text" readonly aria-label="配对链接" hidden></textarea></div><p id="expiry"></p></section><div><section><h2>电脑连接地址</h2><p>手机与电脑使用同一局域网。仅启用你选择的 Wi-Fi 或有线网络地址。</p><div class="interface-actions"><button id="select-all-interfaces">全选</button><button id="invert-interfaces">反选</button><span id="interface-count" aria-live="polite"></span></div><div id="interfaces"></div><button id="apply-interfaces">应用所选地址</button><p id="lan"></p></section><section><h2>待确认的手机</h2><p>核对手机显示的申请码,批准对应的申请。</p><div id="requests"></div></section></div></div></main>
6
+ <main id="connect-page" data-route="connect" hidden><a class="back" href="#tasks">‹ 返回任务总览</a><div class="connect-grid"><section><h2>连接你的手机</h2><p>在 Local Agent Dashboard App 中打开「设置 → 电脑连接 → 扫码连接电脑」,或在手机点击配对链接。</p><button class="primary" id="invite">生成配对邀请</button><div id="qr"></div><div id="invitation-actions" hidden><button id="enlarge-qr">放大二维码</button><button id="copy-pair-link">复制配对链接</button><p id="link-feedback" role="status"></p><a id="pair-link">在手机上打开 App</a><textarea id="pair-link-text" readonly aria-label="配对链接" hidden></textarea></div><p id="expiry"></p></section><div><section><h2>电脑连接地址</h2><p>手机与电脑使用同一局域网。仅启用你选择的 Wi-Fi 或有线网络地址。</p><div class="interface-actions"><button id="select-all-interfaces">全选</button><button id="invert-interfaces">反选</button><span id="interface-count" aria-live="polite"></span></div><div id="interfaces"></div><button id="apply-interfaces">应用所选地址</button><p id="lan"></p></section><section><h2>待确认的手机</h2><p>核对手机显示的申请码,批准对应的申请。</p><div id="requests"></div></section></div></div></main>
7
7
  <main id="devices-page" data-route="devices" hidden><a class="back" href="#tasks">‹ 返回任务总览</a><p class="intro">管理已配对手机,查看最近同步确认。撤销后,该设备将无法继续读取任务。</p><div id="devices"></div><a class="text-link" href="#connect">连接另一台手机 →</a></main>
8
- <dialog id="qr-dialog"><button id="close-qr">关闭</button><p>使用 Agent Signal App 扫码</p><img id="large-qr" alt="放大的手机配对邀请"></dialog><script type="module" src="/app.js"></script></body></html>
8
+ <dialog id="qr-dialog"><button id="close-qr">关闭</button><p>使用 Local Agent Dashboard App 扫码</p><img id="large-qr" alt="放大的手机配对邀请"></dialog><script type="module" src="/app.js"></script></body></html>
package/src/cli.js CHANGED
@@ -12,7 +12,29 @@ const value = (key) => { const i = args.indexOf(key); if (i < 0)
12
12
  throw Error(`${key} 需要参数`); return args[i + 1]; };
13
13
  async function run() {
14
14
  if (args.includes('--help') || args.includes('-h')) {
15
- console.log(`Agent Signal ${metadata.version}\n用法:${command} [--demo] [--no-open] [--state-dir <目录>] [--port <端口>] [--lan-port <端口>] [--hours <1..168>] [--lan <IPv4,IPv4>]\n默认打开本机任务/配置页;在“连接手机”中应用网卡后启用 LAN TLS。\n--doctor 检查依赖;--version 查看版本。\n运行数据:${userRuntimeRoot()}\n依赖:macOS 13+、Node >=22.18、OpenSSL 3(可用 brew install openssl@3)。\n手机使用独立 Android APK;扫码后仍须电脑批准。`);
15
+ console.log(`Local Agent Dashboard ${metadata.version}
16
+ 在 Android 手机上查看这台 Mac 的 Codex 和 Claude Code 任务状态。
17
+
18
+ 启动:${command}
19
+ 启动后会自动打开电脑上的任务总览。要连接手机,请点击页面中的「连接手机」。
20
+
21
+ 常用命令:
22
+ ${command} --doctor 检查运行环境
23
+ ${command} --demo 使用示例任务体验界面
24
+ ${command} --no-open 启动时不自动打开浏览器
25
+ ${command} --version 查看版本
26
+
27
+ 可选参数:
28
+ --state-dir <目录> 指定数据目录
29
+ --port <端口> 电脑管理页面端口(默认自动分配)
30
+ --lan-port <端口> 手机连接端口(默认 63982)
31
+ --hours <1..168> 查看最近多少小时的任务(默认 24)
32
+ --lan <IPv4,IPv4> 启动时启用指定的本机网络地址
33
+
34
+ 数据目录:${userRuntimeRoot()}
35
+ 需要 macOS 13+、Node.js 22.18+ 和 OpenSSL 3。
36
+ 安装 OpenSSL:brew install openssl@3
37
+ 手机需安装 Android App;扫码后,还要在电脑上确认连接。`);
16
38
  return;
17
39
  }
18
40
  if (args.includes('--version')) {
@@ -51,4 +73,4 @@ async function run() {
51
73
  const { main } = await import("./composition/main.js");
52
74
  await main({ runtimeRoot: runtime, openBrowser: true });
53
75
  }
54
- run().catch(e => { console.error(`Agent Signal:${e.message}`); process.exitCode = 1; });
76
+ run().catch(e => { console.error(`Local Agent Dashboard:${e.message}`); process.exitCode = 1; });
@@ -145,7 +145,7 @@ export async function main(options = {}) {
145
145
  browser.on('error', () => { });
146
146
  browser.unref();
147
147
  }
148
- console.log(`Agent Signal(${args.includes('--demo') ? '明确模拟模式' : '只读原生日志'})\n电脑本机管理:${url}\n${endpoints.length ? `LAN TLS:${endpoints.join(', ')}\n首版每次重启需重新批准手机;运行中切换地址保留授权。` : 'LAN 未开启。请在电脑管理页明确选择地址后启用。手机仅使用 Android App。'}`);
148
+ console.log(`Local Agent Dashboard(${args.includes('--demo') ? '示例任务' : '读取本机任务状态'})\n电脑管理页面:${url}\n${endpoints.length ? `手机连接地址:${endpoints.join(', ')}\n服务重启后,需要在电脑上重新确认手机连接。` : '尚未开启手机连接。请在电脑页面点击「连接手机」,选择网络地址后启用。'}`);
149
149
  }
150
150
  catch (e) {
151
151
  clearInterval(renewal);
@@ -1,6 +1,10 @@
1
1
  import { homedir } from 'node:os';
2
+ import { existsSync } from 'node:fs';
2
3
  import { join } from 'node:path';
3
- // npm/npx caches are disposable; computer identity belongs to the user.
4
+ // Keep identities outside disposable npm caches. Reuse legacy data without moving it.
4
5
  export function userRuntimeRoot(home = homedir()) {
5
- return join(home, 'Library', 'Application Support', 'Agent Signal');
6
+ const support = join(home, 'Library', 'Application Support');
7
+ const current = join(support, 'Local Agent Dashboard');
8
+ const legacy = join(support, 'Agent Signal');
9
+ return existsSync(current) || !existsSync(legacy) ? current : legacy;
6
10
  }