jarvis-agent-factory 3.25.2 → 3.26.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.
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # Jarvis Agent Factory · 贾维斯智能体工厂
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
4
- [![Version](https://img.shields.io/badge/version-v3.25.0-green)](https://github.com/Wjl1224734792/Jarvis-Agent-Factory/releases)
4
+ [![Version](https://img.shields.io/badge/version-v3.26.0-green)](https://github.com/Wjl1224734792/Jarvis-Agent-Factory/releases)
5
5
  [![npm](https://img.shields.io/npm/v/jarvis-agent-factory)](https://www.npmjs.com/package/jarvis-agent-factory)
6
6
  <br>**简体中文** | [English](./README_EN.md)
7
7
 
8
8
  跨平台多智能体 AI 编程助手配置集 + MCP 编排引擎。从想法到交付的完整软件开发流水线,支持 **Claude Code / OpenCode / Codex** 三平台。
9
9
 
10
- > **v3.25.0** — API 功能测试 Agent(api-test-expert)· CI/CD 工作流重构 · 文档同步约束强化
10
+ > **v3.26.0** — 会话列表卡片化布局 · 键盘可访问性增强 · 开发环境 MCP 配置
11
11
 
12
12
  ## 快速开始
13
13
 
@@ -71,6 +71,10 @@ jarvis upgrade [path] # 智能升级(只覆盖变更文件
71
71
  jarvis diff [path] # 预览待更新文件
72
72
  jarvis doctor [path] # 健康检查
73
73
 
74
+ jarvis hook gate-check [--session <id>] # 检查当前 Gate 状态(阻断时 exit 1)
75
+ jarvis hook gate-advance [--session <id>] # 推进到下一 Gate
76
+ jarvis hook status [--json] # 流水线会话状态总览
77
+
74
78
  jarvis engine start [--port=N] # 手动启动编排引擎(stdio 模式下 Claude Code 自动拉起)
75
79
  jarvis engine stop / status # 停止 / 状态
76
80
  jarvis web [--port=N] # 启动 Web 面板(独立,需引擎运行)
@@ -151,6 +155,24 @@ test-doc-writer → test-executor → fix-retest
151
155
  | **OpenCode** | `opencode.json` | `type: local` → 自动拉起 `jarvis engine start --stdio` |
152
156
  | **Codex** | `.codex/config.toml` | `url = "localhost:3456/mcp"` → 需引擎已运行 |
153
157
 
158
+ ### 开发环境 MCP
159
+
160
+ 本项目开发时使用 `.mcp.dev.json`,引擎从本地工作区启动(无需全局安装):
161
+
162
+ ```json
163
+ {
164
+ "mcpServers": {
165
+ "jarvis-engine": {
166
+ "type": "stdio",
167
+ "command": "node",
168
+ "args": ["bin/jarvis.js", "engine", "start", "--stdio"]
169
+ }
170
+ }
171
+ }
172
+ ```
173
+
174
+ 切换到开发模式:`cp .mcp.dev.json .mcp.json`(恢复则 `jarvis init -y`)。
175
+
154
176
  ## 生命周期流水线
155
177
 
156
178
  ```
@@ -182,9 +204,9 @@ test-doc-writer → test-executor → fix-retest
182
204
 
183
205
  | | Claude Code | OpenCode | Codex |
184
206
  |---|:--:|:--:|:--:|
185
- | Agents | 53 | 58 | 48 |
207
+ | Agents | 88 | 55 | 45 |
186
208
  | Commands | 16 | 0 | 0 |
187
- | Skills | 28 | 28 | 42 |
209
+ | Skills | 29 | 27 | 42 |
188
210
  | 钩子 | settings.json | 原生插件 (.ts) | hooks.json |
189
211
  | MCP | `.mcp.json` | `opencode.json` | `.codex/config.toml` |
190
212
 
@@ -2,8 +2,8 @@
2
2
  * jarvis hook — Called by Claude Code / OpenCode / Codex hooks.
3
3
  * Uses engine REST API (bypasses MCP transport).
4
4
  *
5
- * jarvis hook gate-check Check current gate (exit 1 if blocked)
6
- * jarvis hook gate-advance Advance to next gate
7
- * jarvis hook status [--json] Pipeline status
5
+ * jarvis hook gate-check [--session <id>] Check current gate (exit 1 if blocked)
6
+ * jarvis hook gate-advance [--session <id>] Advance to next gate
7
+ * jarvis hook status [--json] Pipeline status
8
8
  */
9
9
  export declare function hookCommand(args: any): Promise<void>;
package/dist/src/hook.js CHANGED
@@ -2,9 +2,9 @@
2
2
  * jarvis hook — Called by Claude Code / OpenCode / Codex hooks.
3
3
  * Uses engine REST API (bypasses MCP transport).
4
4
  *
5
- * jarvis hook gate-check Check current gate (exit 1 if blocked)
6
- * jarvis hook gate-advance Advance to next gate
7
- * jarvis hook status [--json] Pipeline status
5
+ * jarvis hook gate-check [--session <id>] Check current gate (exit 1 if blocked)
6
+ * jarvis hook gate-advance [--session <id>] Advance to next gate
7
+ * jarvis hook status [--json] Pipeline status
8
8
  */
9
9
  const ENGINE_URL = process.env.JARVIS_ENGINE_URL || 'http://localhost:3456';
10
10
  async function api(path) {
@@ -13,39 +13,72 @@ async function api(path) {
13
13
  throw new Error(`${r.status}`);
14
14
  return r.json();
15
15
  }
16
+ /** 从 pipeline 响应中解析出最相关的 session */
17
+ function pickSession(pipeline, explicitSid) {
18
+ const sessions = pipeline.sessions || [];
19
+ if (sessions.length === 0)
20
+ return null;
21
+ if (explicitSid) {
22
+ return sessions.find(s => s.session_id === explicitSid) || null;
23
+ }
24
+ // 优先返回 active session,其次返回第一个
25
+ const active = sessions.filter(s => s.status === 'active');
26
+ return active[0] || sessions[0];
27
+ }
16
28
  export async function hookCommand(args) {
17
29
  const sub = args[0];
30
+ // 解析 --session <id> 参数
31
+ const sidIdx = args.indexOf('--session');
32
+ const sessionId = sidIdx >= 0 ? args[sidIdx + 1] : null;
18
33
  if (sub === 'gate-check') {
19
34
  try {
20
- const p = await api('/api/pipeline');
21
- const current = p.current_gate;
22
- const g = await api(`/api/gate/${encodeURIComponent(current)}/enforce`);
35
+ const pipeline = await api('/api/pipeline');
36
+ const session = pickSession(pipeline, sessionId);
37
+ if (!session) {
38
+ console.log('⚠️ No sessions found');
39
+ process.exit(2);
40
+ }
41
+ const current = session.current_gate;
42
+ if (current === 'Complete') {
43
+ console.log('✅ All gates passed');
44
+ process.exit(0);
45
+ }
46
+ const g = await api(`/api/gate/${encodeURIComponent(current)}/enforce?session_id=${session.session_id}`);
23
47
  if (g.allowed) {
24
- console.log(`✅ ${current} — OK`);
48
+ console.log(`✅ ${current} — OK (${session.pipeline_name})`);
25
49
  process.exit(0);
26
50
  }
27
51
  else {
28
- console.log(`🚫 ${current} BLOCKED — ${g.required}`);
52
+ console.log(`🚫 ${current} BLOCKED — ${g.artifacts?.length ? 'missing artifacts' : 'checkpoint required'} (${session.pipeline_name})`);
29
53
  process.exit(1);
30
54
  }
31
55
  }
32
56
  catch {
33
- // Engine not running — warn loudly so user knows enforcement is absent
34
57
  console.error(`\n⚠️ Jarvis Engine is NOT running. Gate enforcement is INACTIVE.`);
35
58
  console.error(` Start it: jarvis engine start\n`);
36
- process.exit(2); // Exit 2 = block (Claude Code treats exit 2 as feedback)
59
+ process.exit(2);
37
60
  }
38
61
  }
39
62
  else if (sub === 'gate-advance') {
40
63
  try {
41
- const r = await fetch(`${ENGINE_URL}/api/gate/advance`, { method: 'POST', headers: { 'Content-Type': 'application/json' } });
64
+ const pipeline = await api('/api/pipeline');
65
+ const session = pickSession(pipeline, sessionId);
66
+ if (!session) {
67
+ console.log('⚠️ No sessions found');
68
+ process.exit(2);
69
+ }
70
+ const r = await fetch(`${ENGINE_URL}/api/gate/advance`, {
71
+ method: 'POST',
72
+ headers: { 'Content-Type': 'application/json' },
73
+ body: JSON.stringify({ gate: session.current_gate, session_id: session.session_id }),
74
+ });
42
75
  const g = await r.json();
43
76
  if (g.allowed) {
44
- console.log(`🚀 ${g.previous} → ${g.current}${g.next ? ` (next: ${g.next})` : ''}`);
77
+ console.log(`🚀 ${g.previous || session.current_gate} → ${g.current}${g.next ? ` (next: ${g.next})` : ''}`);
45
78
  process.exit(0);
46
79
  }
47
80
  else {
48
- console.log(`🚫 BLOCKED — ${g.error}`);
81
+ console.log(`🚫 BLOCKED — ${g.error} (${session.pipeline_name})`);
49
82
  process.exit(1);
50
83
  }
51
84
  }
@@ -57,11 +90,22 @@ export async function hookCommand(args) {
57
90
  }
58
91
  else if (sub === 'status') {
59
92
  try {
60
- const p = await api('/api/pipeline');
61
- if (args.includes('--json'))
62
- console.log(JSON.stringify(p, null, 2));
63
- else
64
- console.log(p._display || `${p.current_gate}`);
93
+ const pipeline = await api('/api/pipeline');
94
+ const sessions = pipeline.sessions || [];
95
+ if (args.includes('--json')) {
96
+ console.log(JSON.stringify(pipeline, null, 2));
97
+ }
98
+ else if (sessions.length === 0) {
99
+ console.log('Engine: running, no sessions');
100
+ }
101
+ else {
102
+ console.log(`Engine: ${sessions.length} session(s), ${pipeline.active_count || sessions.filter(s => s.status === 'active').length} active\n`);
103
+ for (const s of sessions) {
104
+ const badge = s.status === 'active' ? '🟢' : '⚪';
105
+ const task = s.task_name ? ` · ${s.task_name}` : '';
106
+ console.log(` ${badge} ${s.pipeline_name} · ${s.current_gate} · ${s.platform || '?'}${task}`);
107
+ }
108
+ }
65
109
  process.exit(0);
66
110
  }
67
111
  catch {
@@ -70,7 +114,7 @@ export async function hookCommand(args) {
70
114
  }
71
115
  }
72
116
  else {
73
- console.log('Usage: jarvis hook <gate-check|gate-advance|status> [--json]');
117
+ console.log('Usage: jarvis hook <gate-check|gate-advance|status> [--json] [--session <id>]');
74
118
  process.exit(0);
75
119
  }
76
120
  }
@@ -1 +1 @@
1
- {"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/hook.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/hook.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,uBAAuB,CAAC;AAE5E,KAAK,UAAU,GAAG,CAAC,IAAI;IACrB,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,UAAU,GAAG,IAAI,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC,CAAC,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAClB,CAAC;AAED,oCAAoC;AACpC,SAAS,WAAW,CAAC,QAAQ,EAAE,WAAW;IACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC;IACzC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,WAAW,CAAC,IAAI,IAAI,CAAC;IAClE,CAAC;IACD,8BAA8B;IAC9B,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IAC3D,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAI;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,uBAAuB;IACvB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAExD,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,CAAC;YAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YACjD,IAAI,CAAC,OAAO,EAAE,CAAC;gBAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;YACxE,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC;YACrC,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;gBAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;YACnF,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,aAAa,kBAAkB,CAAC,OAAO,CAAC,uBAAuB,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;YACzG,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBAAC,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,UAAU,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;iBAC3F,CAAC;gBAAC,OAAO,CAAC,GAAG,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,qBAAqB,KAAK,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;QACnK,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;YACnF,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;SAEI,IAAI,GAAG,KAAK,cAAc,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,CAAC;YAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YACjD,IAAI,CAAC,OAAO,EAAE,CAAC;gBAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;YACxE,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,UAAU,mBAAmB,EAAE;gBACtD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;aACrF,CAAC,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,YAAY,MAAM,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;iBAC3I,CAAC;gBAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;QAC9F,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAC1E,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;SAEI,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,CAAC;YAC5C,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC;YACzC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACjD,CAAC;iBAAM,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAC9C,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,WAAW,QAAQ,CAAC,MAAM,gBAAgB,QAAQ,CAAC,YAAY,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,MAAM,WAAW,CAAC,CAAC;gBAC9I,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;oBACzB,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;oBACjD,MAAM,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACpD,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,aAAa,MAAM,CAAC,CAAC,YAAY,MAAM,CAAC,CAAC,QAAQ,IAAI,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC;gBACjG,CAAC;YACH,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;SAEI,CAAC;QACJ,OAAO,CAAC,GAAG,CAAC,+EAA+E,CAAC,CAAC;QAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -32,7 +32,7 @@
32
32
  </div>
33
33
  <div>
34
34
  <h1 class="text-[15px] font-bold text-slate-800 leading-tight font-mono tracking-tight">Jarvis Engine</h1>
35
- <p class="text-[11px] text-slate-400 font-mono" id="verNum">v3.25.2</p>
35
+ <p class="text-[11px] text-slate-400 font-mono" id="verNum">v3.26.0</p>
36
36
  </div>
37
37
  </div>
38
38
  </div>
@@ -16,8 +16,6 @@
16
16
  @keyframes spin { from{transform:rotate(0deg);} to{transform:rotate(360deg);} }
17
17
  @keyframes pulse-dot { 0%,100%{opacity:1;} 50%{opacity:.5;} }
18
18
  .refreshing { animation:spin .6s linear; }
19
- .session-item:hover .session-actions { opacity:1; }
20
- .session-actions { opacity:0; transition:opacity .15s; }
21
19
  .live-dot { animation:pulse-dot 2s ease-in-out infinite; }
22
20
  .console-line { border-left: 2px solid #6366F1; padding-left: 10px; }
23
21
  </style>
@@ -34,7 +32,7 @@
34
32
  </div>
35
33
  <div>
36
34
  <h1 class="text-[15px] font-bold text-slate-800 leading-tight font-mono tracking-tight">Jarvis Engine</h1>
37
- <p class="text-[11px] text-slate-400 font-mono" id="verNum">v3.25.2</p>
35
+ <p class="text-[11px] text-slate-400 font-mono" id="verNum">v3.26.0</p>
38
36
  </div>
39
37
  </div>
40
38
  </div>
@@ -529,21 +527,23 @@ function renderSessions() {
529
527
  var pinActionLabel = isPinned ? '取消置顶' : '置顶';
530
528
 
531
529
  return (
532
- '<div class="session-item group flex items-center gap-2.5 px-3 py-2.5 rounded-lg cursor-pointer transition-all ' +
533
- (isActive ? 'bg-indigo-50 border border-indigo-200' : 'hover:bg-slate-50 border border-transparent') +
530
+ '<div class="session-item group flex flex-col gap-1 px-3 py-2 rounded-lg cursor-pointer transition-all ' +
531
+ (isActive ? 'bg-indigo-50 border-l-[3px] border-indigo-500' : 'hover:bg-slate-50 border-l-[3px] border-transparent') +
534
532
  pinnedBorder +
535
- '" onclick="selectSession(\'' + s.id + '\')" title="' + titleTooltip + '">' +
536
- '<div class="flex-1 min-w-0 flex items-center gap-2">' +
533
+ '" role="button" tabindex="0" aria-current="' + (isActive ? 'true' : 'false') + '" onclick="selectSession(\'' + s.id + '\')" onkeydown="if(event.key===\'Enter\'||event.key===\' \'){event.preventDefault();selectSession(\'' + s.id + '\');}" title="' + titleTooltip + '">' +
534
+ '<div class="flex items-center gap-2 min-w-0">' +
537
535
  pinIcon +
538
- '<span class="text-xs text-slate-700 truncate font-medium shrink min-w-0" title="' + displayTitle + '">' + displayTitle + '</span>' +
536
+ '<span class="text-xs text-slate-700 truncate font-semibold flex-1 min-w-0" title="' + displayTitle + '">' + displayTitle + '</span>' +
537
+ '<span class="w-2 h-2 rounded-full flex-shrink-0 ' + statusColor + '" title="' + statusLabel + '"></span>' +
538
+ '</div>' +
539
+ '<div class="flex items-center gap-1.5">' +
539
540
  '<span class="text-[10px] ' + cmdColor + ' px-1.5 py-px rounded font-mono flex-shrink-0 whitespace-nowrap">' + cmd.label + '</span>' +
540
541
  '<span class="text-[10px] text-slate-500 bg-slate-100 px-1.5 py-px rounded font-mono flex-shrink-0">' + (s.gate || '?') + '</span>' +
541
- '</div>' +
542
- '<span class="w-2 h-2 rounded-full flex-shrink-0 ' + statusColor + '" title="' + statusLabel + '"></span>' +
543
- (isInactive ? '<i data-lucide="rotate-ccw" class="session-actions w-3.5 h-3.5 text-indigo-400 flex-shrink-0 hover:text-indigo-300" title="恢复会话" onclick="event.stopPropagation();resumeSession(\'' + s.id + '\')"></i>' : '') +
542
+ (isInactive ? '<button class="w-3.5 h-3.5 flex items-center justify-center bg-transparent border-0 p-0 cursor-pointer text-indigo-400 hover:text-indigo-300 flex-shrink-0 focus-visible:ring-2 focus-visible:ring-indigo-400 focus-visible:outline-none" aria-label="恢复会话" title="恢复会话" onclick="event.stopPropagation();resumeSession(\'' + s.id + '\')"><i data-lucide="rotate-ccw" class="w-3.5 h-3.5"></i></button>' : '') +
543
+ '<div class="flex-1"></div>' +
544
544
  (hasActiveRun ? (
545
545
  '<div class="relative flex-shrink-0">' +
546
- '<button class="session-actions w-5 h-5 flex items-center justify-center rounded hover:bg-slate-200 text-slate-400 hover:text-slate-600 transition-colors" onclick="event.stopPropagation();toggleRunMenu(event, \'' + s.run_id + '\')" title="运行操作">' +
546
+ '<button class="w-5 h-5 flex items-center justify-center rounded hover:bg-slate-200 text-slate-400 hover:text-slate-600 transition-colors focus-visible:ring-2 focus-visible:ring-indigo-400 focus-visible:outline-none" aria-label="运行操作" aria-haspopup="menu" aria-expanded="false" onclick="event.stopPropagation();toggleRunMenu(event, \'' + s.run_id + '\')" title="运行操作">' +
547
547
  '<i data-lucide="more-vertical" class="w-3.5 h-3.5"></i>' +
548
548
  '</button>' +
549
549
  '<div id="run-menu-' + s.run_id + '" class="hidden absolute right-0 top-full mt-1 bg-white rounded-lg shadow-lg border border-slate-200 py-1 z-50 min-w-[112px]" onclick="event.stopPropagation()">' +
@@ -552,7 +552,12 @@ function renderSessions() {
552
552
  '<button class="w-full text-left px-3 py-1.5 text-xs text-red-500 hover:bg-red-50 transition-colors" onclick="event.stopPropagation();deleteRunFromMenu(\'' + s.run_id + '\')">删除</button>' +
553
553
  '</div>' +
554
554
  '</div>'
555
- ) : '') +
555
+ ) : (
556
+ '<button class="w-5 h-5 flex items-center justify-center rounded text-slate-400 cursor-not-allowed flex-shrink-0 focus-visible:ring-2 focus-visible:ring-indigo-400 focus-visible:outline-none" aria-disabled="true" onclick="event.stopPropagation()" title="暂无运行记录">' +
557
+ '<i data-lucide="more-vertical" class="w-3.5 h-3.5"></i>' +
558
+ '</button>'
559
+ )) +
560
+ '</div>' +
556
561
  '</div>'
557
562
  );
558
563
  }).join('');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jarvis-agent-factory",
3
- "version": "3.25.2",
3
+ "version": "3.26.0",
4
4
  "description": "Jarvis Agent Factory CLI — 跨平台多智能体 AI 编程助手配置安装器 | Multi-agent AI coding assistant config installer for Claude Code / OpenCode / Codex",
5
5
  "keywords": [
6
6
  "jarvis",