@k1e1n04/mav 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 (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +212 -0
  3. package/bin/mav.ts +31 -0
  4. package/dist/bin/mav.d.ts +2 -0
  5. package/dist/bin/mav.js +24 -0
  6. package/dist/bin/mav.js.map +1 -0
  7. package/dist/src/agent-launch.d.ts +15 -0
  8. package/dist/src/agent-launch.js +36 -0
  9. package/dist/src/agent-launch.js.map +1 -0
  10. package/dist/src/agent.d.ts +42 -0
  11. package/dist/src/agent.js +209 -0
  12. package/dist/src/agent.js.map +1 -0
  13. package/dist/src/config.d.ts +11 -0
  14. package/dist/src/config.js +32 -0
  15. package/dist/src/config.js.map +1 -0
  16. package/dist/src/current-session.d.ts +15 -0
  17. package/dist/src/current-session.js +17 -0
  18. package/dist/src/current-session.js.map +1 -0
  19. package/dist/src/index.d.ts +6 -0
  20. package/dist/src/index.js +90 -0
  21. package/dist/src/index.js.map +1 -0
  22. package/dist/src/process-cwd.d.ts +1 -0
  23. package/dist/src/process-cwd.js +24 -0
  24. package/dist/src/process-cwd.js.map +1 -0
  25. package/dist/src/session-manager.d.ts +16 -0
  26. package/dist/src/session-manager.js +102 -0
  27. package/dist/src/session-manager.js.map +1 -0
  28. package/dist/src/state.d.ts +19 -0
  29. package/dist/src/state.js +30 -0
  30. package/dist/src/state.js.map +1 -0
  31. package/dist/src/ui/app.d.ts +15 -0
  32. package/dist/src/ui/app.js +109 -0
  33. package/dist/src/ui/app.js.map +1 -0
  34. package/dist/src/ui/detail.d.ts +28 -0
  35. package/dist/src/ui/detail.js +137 -0
  36. package/dist/src/ui/detail.js.map +1 -0
  37. package/dist/src/ui/overview.d.ts +24 -0
  38. package/dist/src/ui/overview.js +267 -0
  39. package/dist/src/ui/overview.js.map +1 -0
  40. package/lua/mav/follow.lua +37 -0
  41. package/lua/mav/init.lua +92 -0
  42. package/lua/mav/state.lua +22 -0
  43. package/package.json +54 -0
  44. package/plugin/mav.lua +24 -0
  45. package/src/agent-launch.ts +43 -0
  46. package/src/agent.ts +243 -0
  47. package/src/config.ts +51 -0
  48. package/src/current-session.ts +34 -0
  49. package/src/index.ts +121 -0
  50. package/src/process-cwd.ts +31 -0
  51. package/src/session-manager.ts +122 -0
  52. package/src/state.ts +49 -0
  53. package/src/types/neo-blessed.d.ts +5 -0
  54. package/src/ui/app.ts +121 -0
  55. package/src/ui/detail.ts +164 -0
  56. package/src/ui/overview.ts +306 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 mav contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,212 @@
1
+ # mav — multi-agent view
2
+
3
+ `mav` is a wrapper CLI that lets you manage multiple AI coding assistant CLIs such as `claude-code`, `codex`, `gemini-cli`, and `copilot` from a single terminal window.
4
+
5
+ ```text
6
+ ┌── AGENTS ────────────────────────────────────────────────────────────────┐
7
+ │ Working │
8
+ │ ⣾ claude-code#1 working │
9
+ │ ⣾ codex#1 working │
10
+ │ Waiting │
11
+ │ ○ gemini-cli#1 waiting │
12
+ │ Complete │
13
+ │ ✓ copilot#1 complete │
14
+ └──────────────────────────────────────────────────────────────────────────┘
15
+ ```
16
+
17
+ ## Features
18
+
19
+ - See multiple AI agent sessions at a glance in one screen
20
+ - Overview groups sessions under `Working / Waiting / Complete / Failed`
21
+ - Open the selected agent in fullscreen with `→` / `Enter`
22
+ - Define startup agents freely with YAML
23
+ - No API key required, as it uses your existing CLI tools directly
24
+
25
+ ## Installation
26
+
27
+ ### Homebrew (Recommended)
28
+
29
+ ```bash
30
+ brew tap k1e1n04/mav https://github.com/k1e1n04/mav.git
31
+ brew install mav
32
+ ```
33
+
34
+ ### npm / pnpm
35
+
36
+ ```bash
37
+ npm install -g @k1e1n04/mav
38
+ # or
39
+ pnpm add -g @k1e1n04/mav
40
+ ```
41
+
42
+ ### Build from Source
43
+
44
+ ```bash
45
+ git clone https://github.com/k1e1n04/mav.git
46
+ cd mav
47
+ pnpm install
48
+ pnpm build
49
+ pnpm link --global
50
+ ```
51
+
52
+ ## Usage
53
+
54
+ ```bash
55
+ mav # Start all agents from the config file
56
+ mav --agent claude-code # Start only the specified agent type
57
+ mav --config ./mav.yaml # Use a custom config file path
58
+ mav --version
59
+ mav --help
60
+ ```
61
+
62
+ If no config file exists at `~/.config/mav/config.yaml`, `mav` starts only `claude`.
63
+
64
+ ## Configuration
65
+
66
+ Create `~/.config/mav/config.yaml`.
67
+
68
+ ```yaml
69
+ agents:
70
+ - type: claude-code
71
+ cmd: claude-launcher # Override the default "claude" command
72
+ args: []
73
+ - type: codex
74
+ # If cmd is omitted, the default "codex" command is used
75
+ - type: gemini-cli
76
+ cmd: gemini
77
+ - type: copilot
78
+ cmd: gh
79
+ args: []
80
+ ```
81
+
82
+ ### Default Commands by Agent Type
83
+
84
+ | type | default cmd |
85
+ |------|----------------|
86
+ | `claude-code` | `claude` |
87
+ | `codex` | `codex` |
88
+ | `gemini-cli` | `gemini` |
89
+ | `copilot` | `copilot` |
90
+
91
+ ## Keybindings
92
+
93
+ | Key | Scope | Action |
94
+ |------|----------|------|
95
+ | `↑` `↓` | Overview | Move through the session list |
96
+ | `→` / `Enter` | Overview | Open the selected session in fullscreen |
97
+ | `Ctrl+]` | Detail | Return to Overview |
98
+ | `n` | Overview | Add a new session |
99
+ | `d` | Overview | Terminate and remove the selected session |
100
+ | `q` / `Ctrl+C` | Overview | Quit `mav` and terminate all sessions |
101
+
102
+ > **Note:** Overview is a progress dashboard. For input and full terminal interaction, use Detail mode. In Detail mode, keys including `←` are passed directly to the agent, so use `Ctrl+]` to return to Overview.
103
+
104
+ ## Neovim Integration
105
+
106
+ `mav` writes the currently selected session to `~/.local/state/mav/current-session.json`.
107
+ This file is intended for editor integrations such as Neovim plugins that want to follow the active session's working directory.
108
+
109
+ ### How the Neovim Plugin Is Provided
110
+
111
+ This repository now includes a Neovim plugin.
112
+
113
+ - `mav` publishes the selected session state as JSON
114
+ - the bundled Neovim plugin reads that file
115
+ - the plugin can follow the selected session by running `:lcd` into its live `cwd`
116
+
117
+ In other words, the stable interface is the state file:
118
+
119
+ ```text
120
+ ~/.local/state/mav/current-session.json
121
+ ```
122
+
123
+ The JSON contains:
124
+
125
+ ```json
126
+ {
127
+ "sessionId": "codex#1",
128
+ "agentType": "codex",
129
+ "displayName": "fix auth redirect",
130
+ "cwd": "/Users/you/Develop/project-a",
131
+ "updatedAt": "2026-05-23T12:34:56.000Z"
132
+ }
133
+ ```
134
+
135
+ The plugin runtime is included in this repo under:
136
+
137
+ ```text
138
+ lua/mav/
139
+ plugin/mav.lua
140
+ ```
141
+
142
+ ### Installation with LazyVim / lazy.nvim
143
+
144
+ Add this to `lua/plugins/mav.lua` in your Neovim config:
145
+
146
+ ```lua
147
+ return {
148
+ {
149
+ "k1e1n04/mav",
150
+ opts = {
151
+ auto_follow = true,
152
+ poll_interval_ms = 500,
153
+ notify_on_switch = false,
154
+ ignore_filetypes = {},
155
+ },
156
+ config = function(_, opts)
157
+ require("mav").setup(opts)
158
+ end,
159
+ },
160
+ }
161
+ ```
162
+
163
+ ### How to Use It
164
+
165
+ 1. Start `mav`.
166
+ 2. Install the plugin from this repo in Neovim using the `lazy.nvim` example above.
167
+ 3. Restart Neovim or reload your plugin config.
168
+ 4. Change the selected session in `mav`.
169
+ 5. Neovim will follow the selected session's current `cwd`, including worktree moves while the agent is running.
170
+
171
+ The plugin exposes:
172
+
173
+ - `:MavFollowNow` to force an immediate refresh
174
+ - `:MavStatus` to print the current selected session name, agent type, and `cwd`
175
+
176
+ ### Plugin Options
177
+
178
+ ```lua
179
+ {
180
+ state_file = vim.fn.expand("~/.local/state/mav/current-session.json"),
181
+ auto_follow = true,
182
+ poll_interval_ms = 500,
183
+ notify_on_switch = false,
184
+ ignore_filetypes = {},
185
+ }
186
+ ```
187
+
188
+ - `state_file`: path to the `mav` state file to watch
189
+ - `auto_follow`: whether polling should automatically update the current window cwd
190
+ - `poll_interval_ms`: polling interval in milliseconds
191
+ - `notify_on_switch`: show a Neovim notification when the followed session changes
192
+ - `ignore_filetypes`: filetypes where follow should be skipped
193
+
194
+ ### Current Limitation
195
+
196
+ Live `cwd` tracking is implemented for macOS and Linux. Updates may lag slightly behind rapid directory changes because `mav` polls the agent process `cwd` on an interval and also consumes terminal current-directory sequences when available.
197
+
198
+ ## Requirements
199
+
200
+ - Node.js 20+
201
+ - Supported platforms: macOS and Linux
202
+
203
+ ## Contributing
204
+
205
+ 1. Fork the repository and run `git checkout -b feat/your-feature`
206
+ 2. Make your changes and add tests with `pnpm test`
207
+ 3. Commit with `git commit -m "feat: your feature"`
208
+ 4. Open a pull request
209
+
210
+ ## License
211
+
212
+ MIT. See [LICENSE](LICENSE) for details.
package/bin/mav.ts ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander'
3
+ import { readFileSync } from 'node:fs'
4
+ import { join, dirname } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+ import { start } from '../src/index.js'
7
+
8
+ const __filename = fileURLToPath(import.meta.url)
9
+ const __dirname = dirname(__filename)
10
+ const pkg = JSON.parse(
11
+ readFileSync(join(__dirname, '..', 'package.json'), 'utf-8')
12
+ ) as { version: string }
13
+
14
+ const program = new Command()
15
+
16
+ program
17
+ .name('mav')
18
+ .description(
19
+ 'Multi-agent view — manage multiple AI CLI sessions in one terminal'
20
+ )
21
+ .version(pkg.version)
22
+ .option('--agent <type>', 'Start only the specified agent type')
23
+ .option('--config <path>', 'Path to config file')
24
+ .action((options: { agent?: string; config?: string }) => {
25
+ start({
26
+ agentType: options.agent,
27
+ configPath: options.config,
28
+ })
29
+ })
30
+
31
+ program.parse()
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { readFileSync } from 'node:fs';
4
+ import { join, dirname } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { start } from '../src/index.js';
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
10
+ const program = new Command();
11
+ program
12
+ .name('mav')
13
+ .description('Multi-agent view — manage multiple AI CLI sessions in one terminal')
14
+ .version(pkg.version)
15
+ .option('--agent <type>', 'Start only the specified agent type')
16
+ .option('--config <path>', 'Path to config file')
17
+ .action((options) => {
18
+ start({
19
+ agentType: options.agent,
20
+ configPath: options.config,
21
+ });
22
+ });
23
+ program.parse();
24
+ //# sourceMappingURL=mav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mav.js","sourceRoot":"","sources":["../../bin/mav.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAEvC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACjD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;AACrC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CACtC,CAAA;AAExB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,KAAK,CAAC;KACX,WAAW,CACV,oEAAoE,CACrE;KACA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;KACpB,MAAM,CAAC,gBAAgB,EAAE,qCAAqC,CAAC;KAC/D,MAAM,CAAC,iBAAiB,EAAE,qBAAqB,CAAC;KAChD,MAAM,CAAC,CAAC,OAA4C,EAAE,EAAE;IACvD,KAAK,CAAC;QACJ,SAAS,EAAE,OAAO,CAAC,KAAK;QACxB,UAAU,EAAE,OAAO,CAAC,MAAM;KAC3B,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEJ,OAAO,CAAC,KAAK,EAAE,CAAA"}
@@ -0,0 +1,15 @@
1
+ export declare const DEFAULT_CMDS: Record<string, {
2
+ cmd: string;
3
+ args: string[];
4
+ resumeArgs?: string[];
5
+ }>;
6
+ export declare function getAgentDefaults(type: string): {
7
+ cmd: string;
8
+ args: string[];
9
+ resumeArgs?: string[];
10
+ };
11
+ /** ツールごとのセッション管理方法を返す */
12
+ export declare function resolveSessionArgs(type: string, baseArgs: string[], savedSessionId: string | undefined, hasSavedState: boolean): {
13
+ args: string[];
14
+ newSessionId?: string;
15
+ };
@@ -0,0 +1,36 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ export const DEFAULT_CMDS = {
3
+ 'claude-code': { cmd: 'claude', args: [] },
4
+ 'codex': { cmd: 'codex', args: [] },
5
+ 'gemini-cli': { cmd: 'gemini', args: [] },
6
+ 'copilot': { cmd: 'copilot', args: [] },
7
+ };
8
+ export function getAgentDefaults(type) {
9
+ return DEFAULT_CMDS[type] ?? { cmd: type, args: [] };
10
+ }
11
+ /** ツールごとのセッション管理方法を返す */
12
+ export function resolveSessionArgs(type, baseArgs, savedSessionId, hasSavedState) {
13
+ switch (type) {
14
+ case 'claude-code':
15
+ case 'gemini-cli': {
16
+ if (savedSessionId) {
17
+ return { args: [...baseArgs, '--resume', savedSessionId] };
18
+ }
19
+ const id = randomUUID();
20
+ return { args: [...baseArgs, '--session-id', id], newSessionId: id };
21
+ }
22
+ case 'copilot': {
23
+ const id = savedSessionId ?? randomUUID();
24
+ return { args: [...baseArgs, '--session-id', id], newSessionId: savedSessionId ? undefined : id };
25
+ }
26
+ case 'codex': {
27
+ if (hasSavedState) {
28
+ return { args: ['resume', '--last'] };
29
+ }
30
+ return { args: baseArgs };
31
+ }
32
+ default:
33
+ return { args: baseArgs };
34
+ }
35
+ }
36
+ //# sourceMappingURL=agent-launch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-launch.js","sourceRoot":"","sources":["../../src/agent-launch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,MAAM,CAAC,MAAM,YAAY,GAA2E;IAClG,aAAa,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE;IAC1C,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE;IACnC,YAAY,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE;IACzC,SAAS,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE;CACxC,CAAA;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAA;AACtD,CAAC;AAED,yBAAyB;AACzB,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,QAAkB,EAClB,cAAkC,EAClC,aAAsB;IAEtB,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,aAAa,CAAC;QACnB,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,IAAI,cAAc,EAAE,CAAC;gBACnB,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,cAAc,CAAC,EAAE,CAAA;YAC5D,CAAC;YACD,MAAM,EAAE,GAAG,UAAU,EAAE,CAAA;YACvB,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAA;QACtE,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,EAAE,GAAG,cAAc,IAAI,UAAU,EAAE,CAAA;YACzC,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;QACnG,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,IAAI,aAAa,EAAE,CAAC;gBAClB,OAAO,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAA;YACvC,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;QAC3B,CAAC;QACD;YACE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;IAC7B,CAAC;AACH,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import type { AgentConfig } from './config.js';
3
+ export type SessionStatus = 'running' | 'idle' | 'done' | 'error';
4
+ export declare class AgentSession extends EventEmitter {
5
+ private static readonly IDLE_TIMEOUT_MS;
6
+ private static readonly DISPLAY_NAME_MAX_LENGTH;
7
+ private static readonly DISPLAY_NAME_MIN_LENGTH;
8
+ private static readonly CWD_POLL_INTERVAL_MS;
9
+ readonly id: string;
10
+ readonly type: string;
11
+ readonly cmd: string;
12
+ cwd: string;
13
+ displayName: string;
14
+ baseArgs: string[];
15
+ status: SessionStatus;
16
+ logBuffer: string[];
17
+ lastPrompt: string;
18
+ sessionId?: string;
19
+ private ptyProcess;
20
+ private exited;
21
+ private idleTimer;
22
+ private cwdPollTimer;
23
+ private displayNameLocked;
24
+ private initialInputBuffer;
25
+ constructor(config: AgentConfig, cols: number, rows: number);
26
+ /** 保存されたdisplayNameを復元し、以降の入力で上書きされないようにロックする */
27
+ restoreDisplayName(name: string): void;
28
+ write(data: string): void;
29
+ kill(): void;
30
+ resize(cols: number, rows: number): void;
31
+ private appendLog;
32
+ private setStatus;
33
+ private scheduleIdleTimer;
34
+ private clearIdleTimer;
35
+ private startCwdPolling;
36
+ private clearCwdPollTimer;
37
+ private updateDisplayNameFromInput;
38
+ private updateCwdFromOutput;
39
+ private updateCwd;
40
+ private static extractOsc7Cwd;
41
+ private static normalizeDisplayName;
42
+ }
@@ -0,0 +1,209 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import * as pty from 'node-pty';
3
+ import { getProcessCwd } from './process-cwd.js';
4
+ const counters = {};
5
+ export class AgentSession extends EventEmitter {
6
+ static IDLE_TIMEOUT_MS = 1500;
7
+ static DISPLAY_NAME_MAX_LENGTH = 25;
8
+ static DISPLAY_NAME_MIN_LENGTH = 3;
9
+ static CWD_POLL_INTERVAL_MS = 1000;
10
+ id;
11
+ type;
12
+ cmd;
13
+ cwd;
14
+ displayName;
15
+ baseArgs = [];
16
+ status = 'running';
17
+ logBuffer = [];
18
+ lastPrompt = '';
19
+ sessionId;
20
+ ptyProcess;
21
+ exited = false;
22
+ idleTimer = null;
23
+ cwdPollTimer = null;
24
+ displayNameLocked = false;
25
+ initialInputBuffer = '';
26
+ constructor(config, cols, rows) {
27
+ super();
28
+ counters[config.type] = (counters[config.type] ?? 0) + 1;
29
+ this.id = `${config.type}#${counters[config.type]}`;
30
+ this.type = config.type;
31
+ this.cmd = config.cmd;
32
+ this.cwd = config.cwd ?? process.cwd();
33
+ this.displayName = `${config.type} ${counters[config.type]}`;
34
+ let proc;
35
+ try {
36
+ proc = pty.spawn(config.cmd, config.args, {
37
+ name: 'xterm-256color',
38
+ cols,
39
+ rows,
40
+ cwd: this.cwd,
41
+ env: process.env,
42
+ });
43
+ }
44
+ catch (err) {
45
+ const msg = err instanceof Error ? err.message : String(err);
46
+ this.exited = true;
47
+ this.status = 'error';
48
+ this.logBuffer.push(`Error: failed to spawn '${config.cmd}': ${msg}\r\n`);
49
+ process.nextTick(() => this.emit('exit', 1));
50
+ return;
51
+ }
52
+ this.ptyProcess = proc;
53
+ this.ptyProcess.onData((data) => {
54
+ this.updateCwdFromOutput(data);
55
+ this.appendLog(data);
56
+ this.setStatus('running');
57
+ this.scheduleIdleTimer();
58
+ this.emit('data', data);
59
+ });
60
+ this.ptyProcess.onExit(({ exitCode }) => {
61
+ this.clearIdleTimer();
62
+ this.clearCwdPollTimer();
63
+ this.setStatus(exitCode === 0 ? 'done' : 'error');
64
+ this.exited = true;
65
+ this.ptyProcess = undefined;
66
+ this.emit('exit', exitCode);
67
+ });
68
+ this.startCwdPolling();
69
+ }
70
+ /** 保存されたdisplayNameを復元し、以降の入力で上書きされないようにロックする */
71
+ restoreDisplayName(name) {
72
+ this.displayName = name;
73
+ this.displayNameLocked = true;
74
+ this.emit('name', name);
75
+ }
76
+ write(data) {
77
+ if (this.exited)
78
+ return;
79
+ this.updateDisplayNameFromInput(data);
80
+ this.ptyProcess?.write(data);
81
+ }
82
+ kill() {
83
+ if (this.exited)
84
+ return;
85
+ this.clearIdleTimer();
86
+ this.clearCwdPollTimer();
87
+ this.ptyProcess?.kill();
88
+ }
89
+ resize(cols, rows) {
90
+ if (this.exited)
91
+ return;
92
+ this.ptyProcess?.resize(cols, rows);
93
+ }
94
+ appendLog(chunk) {
95
+ this.logBuffer.push(chunk);
96
+ if (this.logBuffer.length > 500) {
97
+ this.logBuffer.splice(0, this.logBuffer.length - 500);
98
+ }
99
+ }
100
+ setStatus(nextStatus) {
101
+ if (this.status === nextStatus) {
102
+ return;
103
+ }
104
+ this.status = nextStatus;
105
+ this.emit('status', nextStatus);
106
+ }
107
+ scheduleIdleTimer() {
108
+ if (this.exited)
109
+ return;
110
+ this.clearIdleTimer();
111
+ this.idleTimer = setTimeout(() => {
112
+ this.idleTimer = null;
113
+ if (this.exited)
114
+ return;
115
+ this.setStatus('idle');
116
+ }, AgentSession.IDLE_TIMEOUT_MS);
117
+ }
118
+ clearIdleTimer() {
119
+ if (!this.idleTimer) {
120
+ return;
121
+ }
122
+ clearTimeout(this.idleTimer);
123
+ this.idleTimer = null;
124
+ }
125
+ startCwdPolling() {
126
+ if (this.cwdPollTimer || !this.ptyProcess) {
127
+ return;
128
+ }
129
+ this.cwdPollTimer = setInterval(() => {
130
+ if (this.exited || !this.ptyProcess) {
131
+ return;
132
+ }
133
+ this.updateCwd(getProcessCwd(this.ptyProcess.pid));
134
+ }, AgentSession.CWD_POLL_INTERVAL_MS);
135
+ }
136
+ clearCwdPollTimer() {
137
+ if (!this.cwdPollTimer) {
138
+ return;
139
+ }
140
+ clearInterval(this.cwdPollTimer);
141
+ this.cwdPollTimer = null;
142
+ }
143
+ updateDisplayNameFromInput(data) {
144
+ if (this.displayNameLocked) {
145
+ return;
146
+ }
147
+ this.initialInputBuffer += data;
148
+ // DCS/APC/PM/SOS シーケンス(Warp など一部ターミナルがstdinに送る)を除去してから
149
+ // ユーザー入力の改行を探す。これらのシーケンスは CR/LF を含むことがあり、
150
+ // そのまま処理すると表示名がターミナル固有の文字列で汚染される。
151
+ const cleaned = this.initialInputBuffer.replace(/\x1b[P_^X][^\x1b]*(?:\x1b\\)?/g, '');
152
+ const newlineIndex = cleaned.search(/\r|\n/);
153
+ if (newlineIndex === -1) {
154
+ return;
155
+ }
156
+ const firstLine = cleaned.slice(0, newlineIndex);
157
+ this.initialInputBuffer = '';
158
+ const normalized = AgentSession.normalizeDisplayName(firstLine);
159
+ if (normalized.length < AgentSession.DISPLAY_NAME_MIN_LENGTH) {
160
+ return;
161
+ }
162
+ this.displayNameLocked = true;
163
+ this.displayName = normalized;
164
+ this.emit('name', normalized);
165
+ }
166
+ updateCwdFromOutput(data) {
167
+ this.updateCwd(AgentSession.extractOsc7Cwd(data));
168
+ }
169
+ updateCwd(nextCwd) {
170
+ if (!nextCwd || nextCwd === this.cwd) {
171
+ return;
172
+ }
173
+ this.cwd = nextCwd;
174
+ this.emit('cwd', nextCwd);
175
+ }
176
+ static extractOsc7Cwd(data) {
177
+ const matches = [...data.matchAll(/\x1b\]7;([^\x07\x1b]+)(?:\x07|\x1b\\)/g)];
178
+ const rawUrl = matches.at(-1)?.[1];
179
+ if (!rawUrl) {
180
+ return null;
181
+ }
182
+ try {
183
+ const url = new URL(rawUrl);
184
+ if (url.protocol !== 'file:') {
185
+ return null;
186
+ }
187
+ return decodeURIComponent(url.pathname || '');
188
+ }
189
+ catch {
190
+ return null;
191
+ }
192
+ }
193
+ static normalizeDisplayName(input) {
194
+ const withoutAnsi = input
195
+ .replace(/\x1b[P_^X][^\x1b]*(?:\x1b\\)?/g, '') // DCS, APC, PM, SOS(複数文字シーケンス)
196
+ .replace(/\x1b\][^\x07]*(?:\x07|\x1b\\)/g, '')
197
+ .replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, '')
198
+ .replace(/\x1b[@-Z\\-_]/g, '');
199
+ const collapsed = withoutAnsi
200
+ .replace(/[\x00-\x1f\x7f]+/g, ' ')
201
+ .replace(/\s+/g, ' ')
202
+ .trim();
203
+ if (collapsed.length <= AgentSession.DISPLAY_NAME_MAX_LENGTH) {
204
+ return collapsed;
205
+ }
206
+ return `${collapsed.slice(0, AgentSession.DISPLAY_NAME_MAX_LENGTH - 3).trimEnd()}...`;
207
+ }
208
+ }
209
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface AgentConfig {
2
+ type: string;
3
+ cmd: string;
4
+ args: string[];
5
+ cwd?: string;
6
+ resumeArgs?: string[];
7
+ }
8
+ export interface MavConfig {
9
+ agents: AgentConfig[];
10
+ }
11
+ export declare function loadConfig(configPath: string): MavConfig;
@@ -0,0 +1,32 @@
1
+ import { readFileSync, existsSync } from 'node:fs';
2
+ import { load as yamlLoad } from 'js-yaml';
3
+ import { getAgentDefaults } from './agent-launch.js';
4
+ const DEFAULT_CONFIG = {
5
+ agents: [],
6
+ };
7
+ export function loadConfig(configPath) {
8
+ if (!existsSync(configPath)) {
9
+ return DEFAULT_CONFIG;
10
+ }
11
+ const raw = readFileSync(configPath, 'utf-8');
12
+ const parsed = yamlLoad(raw);
13
+ if (!parsed?.agents || !Array.isArray(parsed.agents)) {
14
+ return DEFAULT_CONFIG;
15
+ }
16
+ const agents = parsed.agents
17
+ .filter((a) => typeof a?.type === 'string' && a.type.length > 0)
18
+ .map((a) => {
19
+ const defaults = getAgentDefaults(a.type);
20
+ const cmd = typeof a.cmd === 'string' && a.cmd.trim().length > 0
21
+ ? a.cmd
22
+ : defaults.cmd;
23
+ return {
24
+ type: a.type,
25
+ cmd,
26
+ args: Array.isArray(a.args) ? a.args : defaults.args,
27
+ resumeArgs: Array.isArray(a.resumeArgs) ? a.resumeArgs : defaults.resumeArgs,
28
+ };
29
+ });
30
+ return { agents };
31
+ }
32
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAcpD,MAAM,cAAc,GAAc;IAChC,MAAM,EAAE,EAAE;CACX,CAAA;AAED,MAAM,UAAU,UAAU,CAAC,UAAkB;IAC3C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,cAAc,CAAA;IACvB,CAAC;IAED,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAC7C,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAwE,CAAA;IAEnG,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,OAAO,cAAc,CAAA;IACvB,CAAC;IAED,MAAM,MAAM,GAAkB,MAAM,CAAC,MAAM;SACxC,MAAM,CAAC,CAAC,CAAC,EAA+E,EAAE,CACzF,OAAO,CAAC,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CACjD;SACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;QACzC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAC9D,CAAC,CAAC,CAAC,CAAC,GAAG;YACP,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAA;QAChB,OAAO;YACL,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,GAAG;YACH,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI;YACpD,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU;SAC7E,CAAA;IACH,CAAC,CAAC,CAAA;IAEJ,OAAO,EAAE,MAAM,EAAE,CAAA;AACnB,CAAC"}