@bbigbang/agent-node 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 (47) hide show
  1. package/dist/agentHost.js +483 -0
  2. package/dist/appVersion.js +14 -0
  3. package/dist/assetCachePaths.js +35 -0
  4. package/dist/attachmentInput.js +588 -0
  5. package/dist/attachmentMaterializer.js +230 -0
  6. package/dist/bigbangCli.js +17 -0
  7. package/dist/bigbangMessageSendDetection.js +284 -0
  8. package/dist/builtinSkillRoots.js +54 -0
  9. package/dist/claudeConfig.js +32 -0
  10. package/dist/claudeDirectRuntime.js +1960 -0
  11. package/dist/claudeSessionControls.js +78 -0
  12. package/dist/claudeTranscriptFs.js +147 -0
  13. package/dist/codexAppServerClient.js +188 -0
  14. package/dist/codexAppServerEnv.js +14 -0
  15. package/dist/codexAppServerRpc.js +273 -0
  16. package/dist/codexAppServerRuntime.js +3495 -0
  17. package/dist/codexBuiltinPrompt.js +117 -0
  18. package/dist/codexConversationSummarizer.js +76 -0
  19. package/dist/codexTranscriptFs.js +145 -0
  20. package/dist/config.js +129 -0
  21. package/dist/connection.js +151 -0
  22. package/dist/dispatchQueueStore.js +39 -0
  23. package/dist/dreamEnv.js +1 -0
  24. package/dist/dreamMemoryFallback.js +118 -0
  25. package/dist/dreamToolPolicy.js +293 -0
  26. package/dist/droidMissionRunner.js +808 -0
  27. package/dist/executor.js +1078 -0
  28. package/dist/hostRuntime.js +1 -0
  29. package/dist/libraryAuthorityFs.js +74 -0
  30. package/dist/libraryMirror.js +183 -0
  31. package/dist/main.js +1659 -0
  32. package/dist/native-worker/native-worker.mjs +475 -0
  33. package/dist/nativeMissionAgentDispatch.js +463 -0
  34. package/dist/nativeMissionRunner.js +461 -0
  35. package/dist/nativeSkillMounts.js +204 -0
  36. package/dist/nativeWorkerHost.js +142 -0
  37. package/dist/nodeSink.js +142 -0
  38. package/dist/panelHttpFetch.js +334 -0
  39. package/dist/runtimeDrivers.js +62 -0
  40. package/dist/skillFs.js +229 -0
  41. package/dist/soloHost.js +165 -0
  42. package/dist/soloNodeSink.js +138 -0
  43. package/dist/terminalManager.js +254 -0
  44. package/dist/workspaceFs.js +1020 -0
  45. package/dist/workspaceGit.js +694 -0
  46. package/dist/workspaceInspect.js +22 -0
  47. package/package.json +49 -0
@@ -0,0 +1,254 @@
1
+ import fs from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import path from 'node:path';
4
+ import { resolveWorkspacePath } from '@bbigbang/runtime-acp';
5
+ const DEFAULT_COLS = 120;
6
+ const DEFAULT_ROWS = 32;
7
+ const MAX_BUFFER_CHARS = 512_000;
8
+ const MAX_STARTUP_COMMAND_CHARS = 512;
9
+ const TERMINAL_BACKEND_UNAVAILABLE_MESSAGE = 'Persistent terminal backend is unavailable on this node.';
10
+ const require = createRequire(import.meta.url);
11
+ export class TerminalManagerError extends Error {
12
+ code;
13
+ constructor(code, message) {
14
+ super(message);
15
+ this.code = code;
16
+ }
17
+ }
18
+ export class TerminalManager {
19
+ sessions = new Map();
20
+ outputListeners = new Set();
21
+ exitListeners = new Set();
22
+ injectedBackend;
23
+ backendState = null;
24
+ constructor(options) {
25
+ this.injectedBackend = options?.backend ?? null;
26
+ }
27
+ isBackendAvailable() {
28
+ return this.getBackendState().available;
29
+ }
30
+ getBackendUnavailableReason() {
31
+ const backend = this.getBackendState();
32
+ return backend.available ? null : backend.reason;
33
+ }
34
+ list(workspaceRoot) {
35
+ this.requireBackend();
36
+ return Array.from(this.sessions.values())
37
+ .filter((session) => session.info.workspaceRoot === workspaceRoot)
38
+ .map((session) => ({ ...session.info }))
39
+ .sort((left, right) => left.createdAt - right.createdAt);
40
+ }
41
+ create(params) {
42
+ const nodePty = this.requireBackend();
43
+ const workspaceRoot = resolveExistingRoot(params.workspaceRoot);
44
+ const cwd = resolveTerminalCwd(workspaceRoot, params.cwd);
45
+ const startupCommand = normalizeStartupCommand(params.startupCommand);
46
+ const closeOnStartupCommand = params.closeOnStartupCommand === true;
47
+ if (closeOnStartupCommand && !startupCommand) {
48
+ throw new TerminalManagerError('invalid_request', 'Terminal closeOnStartupCommand requires a startup command.');
49
+ }
50
+ const cols = normalizeDimension(params.cols, DEFAULT_COLS);
51
+ const rows = normalizeDimension(params.rows, DEFAULT_ROWS);
52
+ const now = Date.now();
53
+ const info = {
54
+ terminalId: params.terminalId,
55
+ workspaceRoot,
56
+ cwd,
57
+ name: params.name?.trim() || `Terminal ${this.list(workspaceRoot).length + 1}`,
58
+ cols,
59
+ rows,
60
+ createdAt: now,
61
+ lastActivityAt: now,
62
+ exited: false,
63
+ exitCode: null,
64
+ signal: null,
65
+ };
66
+ const shell = process.env.SHELL || '/bin/bash';
67
+ const pty = nodePty.spawn(closeOnStartupCommand ? resolveOneShotShell(shell) : shell, closeOnStartupCommand ? ['-lc', startupCommand] : ['-i'], {
68
+ name: 'xterm-256color',
69
+ cols,
70
+ rows,
71
+ cwd,
72
+ env: {
73
+ ...process.env,
74
+ TERM: 'xterm-256color',
75
+ COLORTERM: 'truecolor',
76
+ },
77
+ });
78
+ const session = {
79
+ pty,
80
+ info,
81
+ buffer: '',
82
+ };
83
+ pty.onData((data) => {
84
+ session.info.lastActivityAt = Date.now();
85
+ session.buffer = appendBuffer(session.buffer, data);
86
+ for (const listener of this.outputListeners) {
87
+ listener({ terminalId: info.terminalId, data });
88
+ }
89
+ });
90
+ pty.onExit((event) => {
91
+ const signal = normalizeExitSignal(event.signal);
92
+ session.info.exited = true;
93
+ session.info.exitCode = event.exitCode;
94
+ session.info.signal = signal;
95
+ session.info.lastActivityAt = Date.now();
96
+ for (const listener of this.exitListeners) {
97
+ listener({
98
+ terminalId: info.terminalId,
99
+ exitCode: event.exitCode,
100
+ signal,
101
+ });
102
+ }
103
+ });
104
+ this.sessions.set(info.terminalId, session);
105
+ if (startupCommand && !closeOnStartupCommand) {
106
+ pty.write(`${startupCommand}\n`);
107
+ }
108
+ return { ...info };
109
+ }
110
+ snapshot(terminalId) {
111
+ const session = this.requireSession(terminalId);
112
+ return {
113
+ terminal: { ...session.info },
114
+ buffer: session.buffer,
115
+ };
116
+ }
117
+ input(terminalId, data) {
118
+ const session = this.requireSession(terminalId);
119
+ if (session.info.exited) {
120
+ throw new TerminalManagerError('io_error', 'Terminal has already exited.');
121
+ }
122
+ session.info.lastActivityAt = Date.now();
123
+ session.pty.write(data);
124
+ }
125
+ resize(terminalId, cols, rows) {
126
+ const session = this.requireSession(terminalId);
127
+ const normalizedCols = normalizeDimension(cols, DEFAULT_COLS);
128
+ const normalizedRows = normalizeDimension(rows, DEFAULT_ROWS);
129
+ session.info.cols = normalizedCols;
130
+ session.info.rows = normalizedRows;
131
+ session.info.lastActivityAt = Date.now();
132
+ session.pty.resize(normalizedCols, normalizedRows);
133
+ }
134
+ close(terminalId) {
135
+ const session = this.requireSession(terminalId);
136
+ if (!session.info.exited) {
137
+ session.pty.kill();
138
+ }
139
+ this.sessions.delete(terminalId);
140
+ }
141
+ onOutput(listener) {
142
+ this.outputListeners.add(listener);
143
+ return () => {
144
+ this.outputListeners.delete(listener);
145
+ };
146
+ }
147
+ onExit(listener) {
148
+ this.exitListeners.add(listener);
149
+ return () => {
150
+ this.exitListeners.delete(listener);
151
+ };
152
+ }
153
+ requireSession(terminalId) {
154
+ const session = this.sessions.get(terminalId);
155
+ if (!session) {
156
+ throw new TerminalManagerError('not_found', 'Terminal not found.');
157
+ }
158
+ return session;
159
+ }
160
+ requireBackend() {
161
+ const backend = this.getBackendState();
162
+ if (!backend.available) {
163
+ throw new TerminalManagerError('io_error', backend.reason);
164
+ }
165
+ return backend.module;
166
+ }
167
+ getBackendState() {
168
+ if (this.backendState)
169
+ return this.backendState;
170
+ if (this.injectedBackend) {
171
+ this.backendState = { available: true, module: this.injectedBackend };
172
+ return this.backendState;
173
+ }
174
+ try {
175
+ const module = require('node-pty');
176
+ this.backendState = { available: true, module };
177
+ }
178
+ catch (error) {
179
+ const detail = String(error?.message ?? error);
180
+ this.backendState = {
181
+ available: false,
182
+ reason: `${TERMINAL_BACKEND_UNAVAILABLE_MESSAGE} ${detail}`.trim(),
183
+ };
184
+ }
185
+ return this.backendState;
186
+ }
187
+ }
188
+ function normalizeStartupCommand(value) {
189
+ if (value == null)
190
+ return null;
191
+ if (typeof value !== 'string') {
192
+ throw new TerminalManagerError('invalid_request', 'Terminal startup command must be a string.');
193
+ }
194
+ const trimmed = value.trim();
195
+ if (!trimmed)
196
+ return null;
197
+ if (trimmed.length > MAX_STARTUP_COMMAND_CHARS) {
198
+ throw new TerminalManagerError('invalid_request', `Terminal startup command is too long; maximum is ${MAX_STARTUP_COMMAND_CHARS} characters.`);
199
+ }
200
+ if (/[\r\n]/.test(trimmed)) {
201
+ throw new TerminalManagerError('invalid_request', 'Terminal startup command must be a single line.');
202
+ }
203
+ return trimmed;
204
+ }
205
+ function resolveExistingRoot(workspaceRoot) {
206
+ const resolved = path.resolve(workspaceRoot);
207
+ const stat = fs.statSync(resolved, { throwIfNoEntry: false });
208
+ if (!stat) {
209
+ throw new TerminalManagerError('not_found', 'Workspace root not found.');
210
+ }
211
+ if (!stat.isDirectory()) {
212
+ throw new TerminalManagerError('not_directory', 'Workspace root is not a directory.');
213
+ }
214
+ return resolved;
215
+ }
216
+ function resolveTerminalCwd(workspaceRoot, cwd) {
217
+ if (!cwd)
218
+ return workspaceRoot;
219
+ const absoluteRequested = path.isAbsolute(cwd)
220
+ ? path.resolve(cwd)
221
+ : path.resolve(workspaceRoot, cwd);
222
+ try {
223
+ return resolveWorkspacePath(workspaceRoot, absoluteRequested);
224
+ }
225
+ catch {
226
+ throw new TerminalManagerError('path_outside_workspace', 'Terminal path escapes workspace root.');
227
+ }
228
+ }
229
+ function normalizeDimension(value, fallback) {
230
+ if (!Number.isFinite(value))
231
+ return fallback;
232
+ const normalized = Math.floor(value);
233
+ if (normalized < 20)
234
+ return 20;
235
+ return normalized;
236
+ }
237
+ function resolveOneShotShell(shell) {
238
+ if (path.basename(shell) === 'fish' && fs.existsSync('/bin/bash')) {
239
+ return '/bin/bash';
240
+ }
241
+ return shell;
242
+ }
243
+ function normalizeExitSignal(signal) {
244
+ if (signal == null || signal === 0 || signal === '0') {
245
+ return null;
246
+ }
247
+ return String(signal);
248
+ }
249
+ function appendBuffer(existing, next) {
250
+ const combined = `${existing}${next}`;
251
+ if (combined.length <= MAX_BUFFER_CHARS)
252
+ return combined;
253
+ return combined.slice(combined.length - MAX_BUFFER_CHARS);
254
+ }