@bytespell/amux 0.0.11 → 0.0.13

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 (89) hide show
  1. package/.claude/settings.local.json +11 -0
  2. package/CLAUDE.md +104 -0
  3. package/LICENSE +21 -0
  4. package/README.md +215 -0
  5. package/dist/cli.d.ts +14 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +118 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/client.d.ts +68 -0
  10. package/dist/client.d.ts.map +1 -0
  11. package/dist/client.js +135 -0
  12. package/dist/client.js.map +1 -0
  13. package/dist/index.d.ts +41 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +44 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/{lib/mentions.d.ts → message-parser.d.ts} +3 -5
  18. package/dist/message-parser.d.ts.map +1 -0
  19. package/dist/message-parser.js +45 -0
  20. package/dist/message-parser.js.map +1 -0
  21. package/dist/message-parser.test.d.ts +2 -0
  22. package/dist/message-parser.test.d.ts.map +1 -0
  23. package/dist/message-parser.test.js +188 -0
  24. package/dist/message-parser.test.js.map +1 -0
  25. package/dist/server.d.ts +24 -0
  26. package/dist/server.d.ts.map +1 -0
  27. package/dist/server.js +356 -0
  28. package/dist/server.js.map +1 -0
  29. package/dist/session-updates.d.ts +26 -0
  30. package/dist/session-updates.d.ts.map +1 -0
  31. package/dist/session-updates.js +68 -0
  32. package/dist/session-updates.js.map +1 -0
  33. package/dist/session-updates.test.d.ts +2 -0
  34. package/dist/session-updates.test.d.ts.map +1 -0
  35. package/dist/session-updates.test.js +223 -0
  36. package/dist/session-updates.test.js.map +1 -0
  37. package/dist/session.d.ts +208 -0
  38. package/dist/session.d.ts.map +1 -0
  39. package/dist/session.js +580 -0
  40. package/dist/session.js.map +1 -0
  41. package/dist/state.d.ts +74 -0
  42. package/dist/state.d.ts.map +1 -0
  43. package/dist/state.js +250 -0
  44. package/dist/state.js.map +1 -0
  45. package/dist/terminal.d.ts +47 -0
  46. package/dist/terminal.d.ts.map +1 -0
  47. package/dist/terminal.js +137 -0
  48. package/dist/terminal.js.map +1 -0
  49. package/dist/types.d.ts +64 -2
  50. package/dist/types.d.ts.map +1 -0
  51. package/dist/types.js +16 -31
  52. package/dist/types.js.map +1 -1
  53. package/dist/ws-adapter.d.ts +39 -0
  54. package/dist/ws-adapter.d.ts.map +1 -0
  55. package/dist/ws-adapter.js +198 -0
  56. package/dist/ws-adapter.js.map +1 -0
  57. package/package.json +47 -24
  58. package/src/client.ts +162 -0
  59. package/src/index.ts +66 -0
  60. package/src/message-parser.test.ts +207 -0
  61. package/src/message-parser.ts +54 -0
  62. package/src/session-updates.test.ts +265 -0
  63. package/src/session-updates.ts +87 -0
  64. package/src/session.ts +737 -0
  65. package/src/state.ts +287 -0
  66. package/src/terminal.ts +164 -0
  67. package/src/types.ts +88 -0
  68. package/src/ws-adapter.ts +245 -0
  69. package/tsconfig.json +22 -0
  70. package/vitest.config.ts +7 -0
  71. package/dist/chunk-5IPYOXBE.js +0 -32
  72. package/dist/chunk-5IPYOXBE.js.map +0 -1
  73. package/dist/chunk-C73RKCTS.js +0 -36
  74. package/dist/chunk-C73RKCTS.js.map +0 -1
  75. package/dist/chunk-VVXT4HQM.js +0 -779
  76. package/dist/chunk-VVXT4HQM.js.map +0 -1
  77. package/dist/lib/logger.d.ts +0 -24
  78. package/dist/lib/logger.js +0 -17
  79. package/dist/lib/logger.js.map +0 -1
  80. package/dist/lib/mentions.js +0 -7
  81. package/dist/lib/mentions.js.map +0 -1
  82. package/dist/streams/backends/index.d.ts +0 -88
  83. package/dist/streams/backends/index.js +0 -13
  84. package/dist/streams/backends/index.js.map +0 -1
  85. package/dist/streams/manager.d.ts +0 -55
  86. package/dist/streams/manager.js +0 -248
  87. package/dist/streams/manager.js.map +0 -1
  88. package/dist/types-DCRtrjjj.d.ts +0 -192
  89. package/scripts/fix-pty.cjs +0 -21
package/dist/state.js ADDED
@@ -0,0 +1,250 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ /**
5
+ * Default state directory
6
+ */
7
+ const DEFAULT_STATE_DIR = path.join(os.homedir(), '.local', 'state', 'amux');
8
+ /**
9
+ * State manager for amux sessions.
10
+ * Handles persistence of session state and history.
11
+ */
12
+ export class StateManager {
13
+ stateDir;
14
+ constructor(stateDir) {
15
+ this.stateDir = stateDir ?? DEFAULT_STATE_DIR;
16
+ }
17
+ /**
18
+ * Get the state file path for a specific instance
19
+ */
20
+ getStateFilePath(instanceId) {
21
+ return path.join(this.stateDir, `instance-${instanceId}.json`);
22
+ }
23
+ /**
24
+ * Get history file path for a session
25
+ */
26
+ getHistoryPath(sessionId) {
27
+ return path.join(this.stateDir, `session-${sessionId}-history.json`);
28
+ }
29
+ /**
30
+ * Get sessions registry file path
31
+ */
32
+ getSessionsRegistryPath() {
33
+ return path.join(this.stateDir, 'sessions.json');
34
+ }
35
+ /**
36
+ * Load persisted session state
37
+ */
38
+ loadState(instanceId) {
39
+ console.log('[amux] Loading state for instance:', instanceId);
40
+ try {
41
+ const stateFile = this.getStateFilePath(instanceId);
42
+ if (fs.existsSync(stateFile)) {
43
+ const data = JSON.parse(fs.readFileSync(stateFile, 'utf-8'));
44
+ console.log('[amux] Loaded persisted state:', JSON.stringify(data));
45
+ return data;
46
+ }
47
+ }
48
+ catch (err) {
49
+ console.log('[amux] Failed to load persisted state:', err.message);
50
+ }
51
+ return {};
52
+ }
53
+ /**
54
+ * Save session state to disk
55
+ */
56
+ saveState(instanceId, state) {
57
+ try {
58
+ fs.mkdirSync(this.stateDir, { recursive: true });
59
+ const stateFile = this.getStateFilePath(instanceId);
60
+ fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
61
+ }
62
+ catch (err) {
63
+ console.log('[amux] Failed to save state:', err.message);
64
+ }
65
+ }
66
+ /**
67
+ * Store event to history for replay
68
+ */
69
+ storeEvent(sessionId, event) {
70
+ if (!sessionId)
71
+ return;
72
+ // Only store session updates and turn markers
73
+ const isSessionUpdate = event.type === 'session_update';
74
+ const isTurnMarker = event.type === 'turn_start' || event.type === 'turn_end';
75
+ if (!isSessionUpdate && !isTurnMarker) {
76
+ return;
77
+ }
78
+ try {
79
+ fs.mkdirSync(this.stateDir, { recursive: true });
80
+ const historyFile = this.getHistoryPath(sessionId);
81
+ let events = [];
82
+ if (fs.existsSync(historyFile)) {
83
+ const data = fs.readFileSync(historyFile, 'utf-8');
84
+ events = JSON.parse(data);
85
+ }
86
+ events.push(event);
87
+ fs.writeFileSync(historyFile, JSON.stringify(events));
88
+ }
89
+ catch (err) {
90
+ console.log('[amux] Failed to store event:', err.message);
91
+ }
92
+ }
93
+ /**
94
+ * Load history for replay
95
+ */
96
+ loadHistory(sessionId) {
97
+ if (!sessionId)
98
+ return [];
99
+ try {
100
+ const historyFile = this.getHistoryPath(sessionId);
101
+ if (fs.existsSync(historyFile)) {
102
+ const data = fs.readFileSync(historyFile, 'utf-8');
103
+ return JSON.parse(data);
104
+ }
105
+ }
106
+ catch (err) {
107
+ console.log('[amux] Failed to load history:', err.message);
108
+ }
109
+ return [];
110
+ }
111
+ /**
112
+ * Clear history for a session
113
+ */
114
+ clearHistory(sessionId) {
115
+ if (!sessionId)
116
+ return;
117
+ try {
118
+ const historyFile = this.getHistoryPath(sessionId);
119
+ if (fs.existsSync(historyFile)) {
120
+ fs.unlinkSync(historyFile);
121
+ }
122
+ }
123
+ catch (err) {
124
+ console.log('[amux] Failed to clear history:', err.message);
125
+ }
126
+ }
127
+ /**
128
+ * Load sessions registry
129
+ */
130
+ loadSessionsRegistry() {
131
+ try {
132
+ const registryPath = this.getSessionsRegistryPath();
133
+ if (fs.existsSync(registryPath)) {
134
+ const data = fs.readFileSync(registryPath, 'utf-8');
135
+ return JSON.parse(data);
136
+ }
137
+ }
138
+ catch (err) {
139
+ console.log('[amux] Failed to load sessions registry:', err.message);
140
+ }
141
+ return { sessions: [] };
142
+ }
143
+ /**
144
+ * Save sessions registry
145
+ */
146
+ saveSessionsRegistry(registry) {
147
+ try {
148
+ fs.mkdirSync(this.stateDir, { recursive: true });
149
+ const registryPath = this.getSessionsRegistryPath();
150
+ fs.writeFileSync(registryPath, JSON.stringify(registry, null, 2));
151
+ }
152
+ catch (err) {
153
+ console.log('[amux] Failed to save sessions registry:', err.message);
154
+ }
155
+ }
156
+ /**
157
+ * Register a new session or update existing one
158
+ */
159
+ registerSession(sessionId, cwd, agentType, displayName) {
160
+ const registry = this.loadSessionsRegistry();
161
+ const existingIndex = registry.sessions.findIndex(s => s.id === sessionId);
162
+ const session = {
163
+ id: sessionId,
164
+ name: displayName || `Session ${sessionId.slice(0, 8)}`,
165
+ cwd,
166
+ messageCount: 0,
167
+ lastModified: Date.now(),
168
+ agentType,
169
+ };
170
+ if (existingIndex >= 0) {
171
+ // Update existing session, preserve message count
172
+ const existing = registry.sessions[existingIndex];
173
+ session.messageCount = existing?.messageCount ?? 0;
174
+ registry.sessions[existingIndex] = session;
175
+ }
176
+ else {
177
+ // Add new session at the beginning (most recent first)
178
+ registry.sessions.unshift(session);
179
+ }
180
+ this.saveSessionsRegistry(registry);
181
+ console.log(`[amux] Registered session: ${sessionId}`);
182
+ }
183
+ /**
184
+ * Update session metadata
185
+ */
186
+ updateSessionMetadata(sessionId, updates) {
187
+ const registry = this.loadSessionsRegistry();
188
+ const session = registry.sessions.find(s => s.id === sessionId);
189
+ if (session) {
190
+ if (updates.messageCount !== undefined) {
191
+ session.messageCount = updates.messageCount;
192
+ }
193
+ if (updates.lastModified !== undefined) {
194
+ session.lastModified = updates.lastModified;
195
+ }
196
+ if (updates.name !== undefined) {
197
+ session.name = updates.name;
198
+ }
199
+ this.saveSessionsRegistry(registry);
200
+ }
201
+ }
202
+ /**
203
+ * Increment message count for a session
204
+ */
205
+ incrementSessionMessageCount(sessionId) {
206
+ const registry = this.loadSessionsRegistry();
207
+ const session = registry.sessions.find(s => s.id === sessionId);
208
+ if (session) {
209
+ session.messageCount += 1;
210
+ session.lastModified = Date.now();
211
+ this.saveSessionsRegistry(registry);
212
+ }
213
+ }
214
+ /**
215
+ * List all sessions, optionally filtered by cwd
216
+ */
217
+ listSessions(cwd) {
218
+ const registry = this.loadSessionsRegistry();
219
+ let sessions = registry.sessions;
220
+ // Filter by cwd if provided
221
+ if (cwd) {
222
+ sessions = sessions.filter(s => s.cwd === cwd);
223
+ }
224
+ // Sort by lastModified (most recent first)
225
+ sessions.sort((a, b) => b.lastModified - a.lastModified);
226
+ return sessions;
227
+ }
228
+ /**
229
+ * Get a specific session by ID
230
+ */
231
+ getSession(sessionId) {
232
+ const registry = this.loadSessionsRegistry();
233
+ return registry.sessions.find(s => s.id === sessionId);
234
+ }
235
+ /**
236
+ * Delete a session from the registry and its history
237
+ */
238
+ deleteSession(sessionId) {
239
+ const registry = this.loadSessionsRegistry();
240
+ const index = registry.sessions.findIndex(s => s.id === sessionId);
241
+ if (index >= 0) {
242
+ registry.sessions.splice(index, 1);
243
+ this.saveSessionsRegistry(registry);
244
+ }
245
+ // Also clear the history file
246
+ this.clearHistory(sessionId);
247
+ console.log(`[amux] Deleted session: ${sessionId}`);
248
+ }
249
+ }
250
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { type ChildProcess } from 'child_process';
2
+ import type * as acp from '@agentclientprotocol/sdk';
3
+ /**
4
+ * Terminal state tracking
5
+ */
6
+ export interface TerminalState {
7
+ process: ChildProcess;
8
+ output: string;
9
+ exitCode: number | null;
10
+ signal: string | null;
11
+ truncated: boolean;
12
+ outputByteLimit: number;
13
+ }
14
+ /**
15
+ * Manages terminal processes for ACP terminal capability.
16
+ * Handles spawning, output collection, and lifecycle management.
17
+ */
18
+ export declare class TerminalManager {
19
+ private defaultCwd;
20
+ private terminals;
21
+ constructor(defaultCwd: () => string);
22
+ /**
23
+ * Create a new terminal process
24
+ */
25
+ create(params: acp.CreateTerminalRequest): acp.CreateTerminalResponse;
26
+ /**
27
+ * Get terminal output
28
+ */
29
+ getOutput(terminalId: string): acp.TerminalOutputResponse;
30
+ /**
31
+ * Wait for terminal to exit
32
+ */
33
+ waitForExit(terminalId: string): Promise<acp.WaitForTerminalExitResponse>;
34
+ /**
35
+ * Kill a terminal process
36
+ */
37
+ kill(terminalId: string): acp.KillTerminalCommandResponse;
38
+ /**
39
+ * Release a terminal (cleanup)
40
+ */
41
+ release(terminalId: string): acp.ReleaseTerminalResponse;
42
+ /**
43
+ * Kill all terminals (for shutdown)
44
+ */
45
+ killAll(): void;
46
+ }
47
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,qBAAa,eAAe;IAGd,OAAO,CAAC,UAAU;IAF9B,OAAO,CAAC,SAAS,CAAoC;gBAEjC,UAAU,EAAE,MAAM,MAAM;IAE5C;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,qBAAqB,GAAG,GAAG,CAAC,sBAAsB;IAqDrE;;OAEG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,sBAAsB;IAezD;;OAEG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;IAyB/E;;OAEG;IACH,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,2BAA2B;IASzD;;OAEG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,uBAAuB;IAWxD;;OAEG;IACH,OAAO,IAAI,IAAI;CAOhB"}
@@ -0,0 +1,137 @@
1
+ import { spawn } from 'child_process';
2
+ import crypto from 'crypto';
3
+ /**
4
+ * Manages terminal processes for ACP terminal capability.
5
+ * Handles spawning, output collection, and lifecycle management.
6
+ */
7
+ export class TerminalManager {
8
+ defaultCwd;
9
+ terminals = new Map();
10
+ constructor(defaultCwd) {
11
+ this.defaultCwd = defaultCwd;
12
+ }
13
+ /**
14
+ * Create a new terminal process
15
+ */
16
+ create(params) {
17
+ console.log('[amux] Create terminal:', params.command);
18
+ const terminalId = crypto.randomUUID();
19
+ const outputByteLimit = Number(params.outputByteLimit ?? 1024 * 1024); // Default 1MB
20
+ const termProc = spawn(params.command, params.args ?? [], {
21
+ cwd: params.cwd ?? this.defaultCwd(),
22
+ env: params.env
23
+ ? { ...process.env, ...Object.fromEntries(params.env.map(e => [e.name, e.value])) }
24
+ : process.env,
25
+ shell: true,
26
+ stdio: ['ignore', 'pipe', 'pipe'],
27
+ });
28
+ const terminal = {
29
+ process: termProc,
30
+ output: '',
31
+ exitCode: null,
32
+ signal: null,
33
+ truncated: false,
34
+ outputByteLimit,
35
+ };
36
+ const appendOutput = (data) => {
37
+ terminal.output += data.toString();
38
+ // Truncate from beginning if over limit
39
+ if (terminal.output.length > terminal.outputByteLimit) {
40
+ terminal.output = terminal.output.slice(-terminal.outputByteLimit);
41
+ terminal.truncated = true;
42
+ }
43
+ };
44
+ termProc.stdout?.on('data', appendOutput);
45
+ termProc.stderr?.on('data', appendOutput);
46
+ termProc.on('exit', (code, signal) => {
47
+ console.log(`[amux] Terminal ${terminalId} exited with code ${code}, signal ${signal}`);
48
+ terminal.exitCode = code ?? null;
49
+ terminal.signal = signal ?? null;
50
+ });
51
+ termProc.on('error', (err) => {
52
+ console.error(`[amux] Terminal ${terminalId} error:`, err.message);
53
+ terminal.output += `\nError: ${err.message}`;
54
+ terminal.exitCode = -1;
55
+ });
56
+ this.terminals.set(terminalId, terminal);
57
+ console.log(`[amux] Created terminal ${terminalId} for command: ${params.command}`);
58
+ return { terminalId };
59
+ }
60
+ /**
61
+ * Get terminal output
62
+ */
63
+ getOutput(terminalId) {
64
+ const terminal = this.terminals.get(terminalId);
65
+ if (!terminal) {
66
+ throw new Error(`Terminal ${terminalId} not found`);
67
+ }
68
+ return {
69
+ output: terminal.output,
70
+ truncated: terminal.truncated,
71
+ exitStatus: terminal.exitCode !== null || terminal.signal !== null ? {
72
+ exitCode: terminal.exitCode,
73
+ signal: terminal.signal,
74
+ } : undefined,
75
+ };
76
+ }
77
+ /**
78
+ * Wait for terminal to exit
79
+ */
80
+ async waitForExit(terminalId) {
81
+ const terminal = this.terminals.get(terminalId);
82
+ if (!terminal) {
83
+ throw new Error(`Terminal ${terminalId} not found`);
84
+ }
85
+ // If already exited, return immediately
86
+ if (terminal.exitCode !== null || terminal.signal !== null) {
87
+ return {
88
+ exitCode: terminal.exitCode,
89
+ signal: terminal.signal,
90
+ };
91
+ }
92
+ // Wait for exit
93
+ return new Promise((resolve) => {
94
+ terminal.process.on('exit', (code, signal) => {
95
+ resolve({
96
+ exitCode: code ?? null,
97
+ signal: signal ?? null,
98
+ });
99
+ });
100
+ });
101
+ }
102
+ /**
103
+ * Kill a terminal process
104
+ */
105
+ kill(terminalId) {
106
+ const terminal = this.terminals.get(terminalId);
107
+ if (!terminal) {
108
+ throw new Error(`Terminal ${terminalId} not found`);
109
+ }
110
+ terminal.process.kill('SIGTERM');
111
+ return {};
112
+ }
113
+ /**
114
+ * Release a terminal (cleanup)
115
+ */
116
+ release(terminalId) {
117
+ const terminal = this.terminals.get(terminalId);
118
+ if (terminal) {
119
+ if (terminal.exitCode === null) {
120
+ terminal.process.kill('SIGKILL');
121
+ }
122
+ this.terminals.delete(terminalId);
123
+ }
124
+ return {};
125
+ }
126
+ /**
127
+ * Kill all terminals (for shutdown)
128
+ */
129
+ killAll() {
130
+ for (const [terminalId, terminal] of this.terminals) {
131
+ console.log(`[amux] Killing terminal ${terminalId}`);
132
+ terminal.process.kill('SIGKILL');
133
+ }
134
+ this.terminals.clear();
135
+ }
136
+ }
137
+ //# sourceMappingURL=terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,2 +1,64 @@
1
- export { A as AcpEvent, h as AcpLifecycleEvent, E as Emit, L as LifecycleEvent, g as ModeInfo, M as ModelInfo, N as NormalizedPlanEntry, P as PendingPermission, S as StartStreamArgs, i as StreamEvent, a as StreamHandle, b as StreamPayload, T as TerminalEvent, k as isAcpEvent, l as isAcpLifecycleEvent, j as isLifecycleEvent, m as isTerminalEvent, n as normalizePlanEntry } from './types-DCRtrjjj.js';
2
- export { PlanEntry as AcpPlanEntry, AudioContent, AvailableCommand, AvailableCommandsUpdate, ContentBlock, ContentChunk, CurrentModeUpdate, EmbeddedResource, ImageContent, PermissionOption, Plan, PlanEntryPriority, PlanEntryStatus, RequestPermissionRequest, RequestPermissionResponse, ResourceLink, SessionUpdate, TextContent, ToolCall, ToolCallStatus, ToolCallUpdate } from '@agentclientprotocol/sdk';
1
+ import type * as acp from '@agentclientprotocol/sdk';
2
+ /**
3
+ * Agent configuration - maps agent type to binary name
4
+ */
5
+ export interface AgentConfig {
6
+ name: string;
7
+ bin: string;
8
+ }
9
+ /**
10
+ * Built-in agent registry
11
+ */
12
+ export declare const AGENTS: Record<string, AgentConfig>;
13
+ /**
14
+ * Session metadata for persistence
15
+ */
16
+ export interface SessionMetadata {
17
+ id: string;
18
+ name: string;
19
+ cwd: string;
20
+ messageCount: number;
21
+ lastModified: number;
22
+ agentType: string;
23
+ }
24
+ /**
25
+ * Persisted session state
26
+ */
27
+ export interface SessionState {
28
+ cwd?: string;
29
+ sessionId?: string | null;
30
+ agentType?: string;
31
+ }
32
+ /**
33
+ * Event stored in history for replay
34
+ */
35
+ export interface StoredEvent {
36
+ type: string;
37
+ update?: acp.SessionUpdate;
38
+ [key: string]: unknown;
39
+ }
40
+ /**
41
+ * Session restore info sent to UI
42
+ */
43
+ export interface SessionRestoreInfo {
44
+ restored: boolean;
45
+ reason?: string;
46
+ }
47
+ /**
48
+ * Configuration for creating an agent session
49
+ */
50
+ export interface AgentSessionConfig {
51
+ /** Unique identifier for this session instance */
52
+ instanceId: string;
53
+ /** Base path for resolving agent binaries (node_modules/.bin) */
54
+ basePath: string;
55
+ /** Optional system context to inject (e.g., from a markdown file) */
56
+ systemContext?: string;
57
+ /** Optional fixed working directory (overrides user selection) */
58
+ fixedCwd?: string;
59
+ /** Optional initial agent type (defaults to 'claude-code') */
60
+ agentType?: string;
61
+ /** Optional state directory override */
62
+ stateDir?: string;
63
+ }
64
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAa9C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IAEnB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IAEjB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
package/dist/types.js CHANGED
@@ -1,33 +1,18 @@
1
- // src/types.ts
2
- function normalizePlanEntry(entry) {
3
- const meta = entry._meta;
4
- const claudeCode = meta?.claudeCode;
5
- const activeForm = claudeCode?.activeForm;
6
- const directActiveForm = entry.activeForm;
7
- return {
8
- content: entry.content,
9
- status: entry.status,
10
- priority: entry.priority,
11
- activeForm: activeForm ?? directActiveForm
12
- };
13
- }
14
- function isLifecycleEvent(payload) {
15
- return payload.eventType === "ready" || payload.eventType === "error" || payload.eventType === "stopped";
16
- }
17
- function isAcpEvent(payload) {
18
- return payload.eventType === "acp";
19
- }
20
- function isAcpLifecycleEvent(payload) {
21
- return typeof payload.eventType === "string" && payload.eventType.startsWith("acp:");
22
- }
23
- function isTerminalEvent(payload) {
24
- return typeof payload.eventType === "string" && payload.eventType.startsWith("terminal:");
25
- }
26
- export {
27
- isAcpEvent,
28
- isAcpLifecycleEvent,
29
- isLifecycleEvent,
30
- isTerminalEvent,
31
- normalizePlanEntry
1
+ /**
2
+ * Built-in agent registry
3
+ */
4
+ export const AGENTS = {
5
+ 'claude-code': {
6
+ name: 'Claude Code',
7
+ bin: 'claude-code-acp',
8
+ },
9
+ 'codex': {
10
+ name: 'Codex',
11
+ bin: 'codex-acp',
12
+ },
13
+ 'pi': {
14
+ name: 'Pi',
15
+ bin: 'pi-acp',
16
+ },
32
17
  };
33
18
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts"],"sourcesContent":["// Re-export ACP types from SDK\nexport type {\n SessionUpdate,\n ContentBlock,\n ContentChunk,\n TextContent,\n ImageContent,\n AudioContent,\n EmbeddedResource,\n ResourceLink,\n PlanEntry as AcpPlanEntry,\n PlanEntryPriority,\n PlanEntryStatus,\n Plan,\n AvailableCommand,\n AvailableCommandsUpdate,\n CurrentModeUpdate,\n ToolCall,\n ToolCallUpdate,\n ToolCallStatus,\n PermissionOption,\n RequestPermissionRequest,\n RequestPermissionResponse,\n} from '@agentclientprotocol/sdk';\n\nimport type { PlanEntry as AcpPlanEntry, PlanEntryPriority, PlanEntryStatus, SessionUpdate } from '@agentclientprotocol/sdk';\n\n/**\n * Normalized PlanEntry that handles agent-specific quirks.\n *\n * Standard ACP: content, priority, status\n * Claude-style: content, status, activeForm (priority always \"medium\")\n *\n * The `activeForm` field provides a present-tense description (e.g., \"Analyzing tests\")\n * vs the imperative `content` (e.g., \"Analyze tests\"). When `activeForm` is present\n * and the status is \"in_progress\", UI should prefer displaying `activeForm`.\n */\nexport interface NormalizedPlanEntry {\n content: string;\n status: PlanEntryStatus;\n priority: PlanEntryPriority;\n /** Present-tense form for in_progress display (Claude-style). */\n activeForm?: string;\n}\n\n/**\n * Normalize an incoming ACP plan entry.\n * Extracts `activeForm` from Claude's `_meta.claudeCode` extension if present.\n */\nexport function normalizePlanEntry(entry: AcpPlanEntry): NormalizedPlanEntry {\n // Try to extract activeForm from _meta.claudeCode (if claude-acp sends it there)\n const meta = entry._meta as Record<string, unknown> | undefined;\n const claudeCode = meta?.claudeCode as Record<string, unknown> | undefined;\n const activeForm = claudeCode?.activeForm as string | undefined;\n\n // Also check if activeForm is directly on the entry (non-standard but possible)\n const directActiveForm = (entry as Record<string, unknown>).activeForm as string | undefined;\n\n return {\n content: entry.content,\n status: entry.status,\n priority: entry.priority,\n activeForm: activeForm ?? directActiveForm,\n };\n}\n\n// Model and mode info returned from stream session\nexport interface ModelInfo {\n modelId: string;\n name: string;\n}\n\nexport interface ModeInfo {\n id: string;\n name: string;\n description?: string;\n}\n\n// Permission types for WebSocket push\nexport interface PendingPermission {\n requestId: string;\n toolCallId?: string;\n title: string;\n options: Array<{ optionId: string; name: string; kind: string }>;\n}\n\n// ============================================================================\n// Generic Event System\n//\n// All events have an `eventType` discriminant. Known events are typed precisely;\n// plugins use the generic escape hatch { eventType: string; [key: string]: unknown }.\n// ============================================================================\n\n/**\n * Universal lifecycle events that ALL drivers should emit.\n */\nexport type LifecycleEvent =\n | { eventType: 'ready' }\n | { eventType: 'error'; message: string }\n | { eventType: 'stopped' };\n\n/**\n * ACP session update events (from ACP driver).\n * Wraps the ACP SessionUpdate with eventType discriminant.\n */\nexport type AcpEvent = { eventType: 'acp' } & SessionUpdate;\n\n/**\n * ACP-specific lifecycle events (turns, permissions).\n * Only the ACP driver emits these.\n */\nexport type AcpLifecycleEvent =\n | { eventType: 'acp:turn_start' }\n | { eventType: 'acp:turn_end' }\n | { eventType: 'acp:turn_cancelled' }\n | { eventType: 'acp:permission_request'; permission: PendingPermission }\n | { eventType: 'acp:permission_cleared' };\n\n/**\n * Terminal events (from PTY/shell driver).\n */\nexport type TerminalEvent =\n | { eventType: 'terminal:output'; data: string }\n | { eventType: 'terminal:exit'; exitCode: number | null; signal: string | null };\n\n/**\n * All known event types, plus a generic escape hatch for plugins.\n * Plugins can emit { eventType: 'my-plugin:custom', ...data } and renderers\n * can handle them with type narrowing.\n */\nexport type StreamPayload =\n | LifecycleEvent\n | AcpEvent\n | AcpLifecycleEvent\n | TerminalEvent\n | { eventType: string; [key: string]: unknown };\n\n/**\n * StreamEvent = payload with metadata stamped at emission time.\n */\nexport type StreamEvent = StreamPayload & {\n streamId: string;\n timestamp: number;\n};\n\n/**\n * Emit callback type for library consumers.\n */\nexport type Emit = (event: StreamEvent) => void;\n\n// Type guard helpers\nexport function isLifecycleEvent(payload: StreamPayload): payload is LifecycleEvent {\n return payload.eventType === 'ready' || payload.eventType === 'error' || payload.eventType === 'stopped';\n}\n\nexport function isAcpEvent(payload: StreamPayload): payload is AcpEvent {\n return payload.eventType === 'acp';\n}\n\nexport function isAcpLifecycleEvent(payload: StreamPayload): payload is AcpLifecycleEvent {\n return typeof payload.eventType === 'string' && payload.eventType.startsWith('acp:');\n}\n\nexport function isTerminalEvent(payload: StreamPayload): payload is TerminalEvent {\n return typeof payload.eventType === 'string' && payload.eventType.startsWith('terminal:');\n}\n\n// Handle returned from startStream for the caller to use\nexport interface StreamHandle {\n streamId: string;\n stream: import('./streams/backends/types.js').Stream;\n /** Driver type that handled this stream */\n driverType: string;\n}\n\n// Arguments for starting a stream\nexport interface StartStreamArgs {\n streamId: string;\n /** Driver type to route to (e.g., 'acp', 'pty', or custom plugin types) */\n driverType: string;\n config: import('./streams/backends/types.js').StreamConfig;\n cwd: string;\n restoredState?: unknown;\n emit: Emit;\n /** Directory for driver to store persistent data (e.g. history.json) */\n storageDir: string;\n}\n"],"mappings":";AAiDO,SAAS,mBAAmB,OAA0C;AAE3E,QAAM,OAAO,MAAM;AACnB,QAAM,aAAa,MAAM;AACzB,QAAM,aAAa,YAAY;AAG/B,QAAM,mBAAoB,MAAkC;AAE5D,SAAO;AAAA,IACL,SAAS,MAAM;AAAA,IACf,QAAQ,MAAM;AAAA,IACd,UAAU,MAAM;AAAA,IAChB,YAAY,cAAc;AAAA,EAC5B;AACF;AAuFO,SAAS,iBAAiB,SAAmD;AAClF,SAAO,QAAQ,cAAc,WAAW,QAAQ,cAAc,WAAW,QAAQ,cAAc;AACjG;AAEO,SAAS,WAAW,SAA6C;AACtE,SAAO,QAAQ,cAAc;AAC/B;AAEO,SAAS,oBAAoB,SAAsD;AACxF,SAAO,OAAO,QAAQ,cAAc,YAAY,QAAQ,UAAU,WAAW,MAAM;AACrF;AAEO,SAAS,gBAAgB,SAAkD;AAChF,SAAO,OAAO,QAAQ,cAAc,YAAY,QAAQ,UAAU,WAAW,WAAW;AAC1F;","names":[]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAgC;IACjD,aAAa,EAAE;QACb,IAAI,EAAE,aAAa;QACnB,GAAG,EAAE,iBAAiB;KACvB;IACD,OAAO,EAAE;QACP,IAAI,EAAE,OAAO;QACb,GAAG,EAAE,WAAW;KACjB;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,IAAI;QACV,GAAG,EAAE,QAAQ;KACd;CACF,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { WebSocketServer } from 'ws';
2
+ import type { AgentSession } from './session.js';
3
+ /**
4
+ * Options for the WebSocket adapter
5
+ */
6
+ export interface WsAdapterOptions {
7
+ /**
8
+ * Send history on connect (default: true)
9
+ */
10
+ sendHistoryOnConnect?: boolean;
11
+ }
12
+ /**
13
+ * Create a WebSocket adapter for an AgentSession.
14
+ *
15
+ * Bridges session events to WebSocket clients and handles incoming messages.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { AgentSession } from 'amux';
20
+ * import { createWsAdapter } from 'amux/ws';
21
+ * import { WebSocketServer } from 'ws';
22
+ *
23
+ * const session = new AgentSession({ ... });
24
+ * const wss = new WebSocketServer({ server, path: '/ws' });
25
+ *
26
+ * createWsAdapter(session, wss);
27
+ *
28
+ * await session.spawnAgent();
29
+ * ```
30
+ */
31
+ export declare function createWsAdapter(session: AgentSession, wss: WebSocketServer, options?: WsAdapterOptions): {
32
+ /** Get connected client count */
33
+ clientCount: () => number;
34
+ /** Broadcast a custom message to all clients */
35
+ broadcast: (message: unknown) => void;
36
+ /** Close all connections */
37
+ close: () => void;
38
+ };
39
+ //# sourceMappingURL=ws-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-adapter.d.ts","sourceRoot":"","sources":["../src/ws-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,eAAe,EAAE,MAAM,IAAI,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAsB,MAAM,cAAc,CAAC;AAUrE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,YAAY,EACrB,GAAG,EAAE,eAAe,EACpB,OAAO,GAAE,gBAAqB,GAC7B;IACD,iCAAiC;IACjC,WAAW,EAAE,MAAM,MAAM,CAAC;IAC1B,gDAAgD;IAChD,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,4BAA4B;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAmGA"}