iosm-cli 0.2.15 → 0.2.16
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/CHANGELOG.md +32 -0
- package/README.md +18 -1
- package/dist/cli/args.d.ts +2 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +16 -3
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-profiles.d.ts.map +1 -1
- package/dist/core/agent-profiles.js +3 -0
- package/dist/core/agent-profiles.js.map +1 -1
- package/dist/core/agent-session.d.ts +2 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +26 -10
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/agent-teams.d.ts.map +1 -1
- package/dist/core/agent-teams.js +12 -9
- package/dist/core/agent-teams.js.map +1 -1
- package/dist/core/checkpoint/fs-checkpoint.d.ts +14 -0
- package/dist/core/checkpoint/fs-checkpoint.d.ts.map +1 -0
- package/dist/core/checkpoint/fs-checkpoint.js +211 -0
- package/dist/core/checkpoint/fs-checkpoint.js.map +1 -0
- package/dist/core/command-dispatcher.d.ts +2 -0
- package/dist/core/command-dispatcher.d.ts.map +1 -1
- package/dist/core/command-dispatcher.js +78 -13
- package/dist/core/command-dispatcher.js.map +1 -1
- package/dist/core/mcp/cli.d.ts.map +1 -1
- package/dist/core/mcp/cli.js +26 -0
- package/dist/core/mcp/cli.js.map +1 -1
- package/dist/core/mcp/config.d.ts.map +1 -1
- package/dist/core/mcp/config.js +55 -0
- package/dist/core/mcp/config.js.map +1 -1
- package/dist/core/mcp/index.d.ts +1 -1
- package/dist/core/mcp/index.d.ts.map +1 -1
- package/dist/core/mcp/index.js.map +1 -1
- package/dist/core/mcp/runtime.d.ts +3 -1
- package/dist/core/mcp/runtime.d.ts.map +1 -1
- package/dist/core/mcp/runtime.js +21 -2
- package/dist/core/mcp/runtime.js.map +1 -1
- package/dist/core/mcp/types.d.ts +30 -2
- package/dist/core/mcp/types.d.ts.map +1 -1
- package/dist/core/mcp/types.js.map +1 -1
- package/dist/core/package-manager.d.ts +10 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +100 -2
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/policy/engine.d.ts +77 -0
- package/dist/core/policy/engine.d.ts.map +1 -0
- package/dist/core/policy/engine.js +614 -0
- package/dist/core/policy/engine.js.map +1 -0
- package/dist/core/policy/index.d.ts +2 -0
- package/dist/core/policy/index.d.ts.map +1 -0
- package/dist/core/policy/index.js +2 -0
- package/dist/core/policy/index.js.map +1 -0
- package/dist/core/sandbox/executor.d.ts +13 -0
- package/dist/core/sandbox/executor.d.ts.map +1 -0
- package/dist/core/sandbox/executor.js +64 -0
- package/dist/core/sandbox/executor.js.map +1 -0
- package/dist/core/sdk.d.ts +2 -2
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +3 -3
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/security/index.d.ts +3 -0
- package/dist/core/security/index.d.ts.map +1 -0
- package/dist/core/security/index.js +3 -0
- package/dist/core/security/index.js.map +1 -0
- package/dist/core/security/source-security.d.ts +43 -0
- package/dist/core/security/source-security.d.ts.map +1 -0
- package/dist/core/security/source-security.js +94 -0
- package/dist/core/security/source-security.js.map +1 -0
- package/dist/core/security/trust-ledger.d.ts +24 -0
- package/dist/core/security/trust-ledger.d.ts.map +1 -0
- package/dist/core/security/trust-ledger.js +66 -0
- package/dist/core/security/trust-ledger.js.map +1 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +128 -15
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +6 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +22 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +9 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/task-plan.d.ts +1 -0
- package/dist/core/task-plan.d.ts.map +1 -1
- package/dist/core/task-plan.js +103 -0
- package/dist/core/task-plan.js.map +1 -1
- package/dist/core/tools/apply-patch.d.ts +29 -0
- package/dist/core/tools/apply-patch.d.ts.map +1 -0
- package/dist/core/tools/apply-patch.js +167 -0
- package/dist/core/tools/apply-patch.js.map +1 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +15 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/git-common.d.ts.map +1 -1
- package/dist/core/tools/git-common.js +15 -1
- package/dist/core/tools/git-common.js.map +1 -1
- package/dist/core/tools/index.d.ts +20 -2
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +85 -25
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/permissions.d.ts +16 -0
- package/dist/core/tools/permissions.d.ts.map +1 -1
- package/dist/core/tools/permissions.js +34 -1
- package/dist/core/tools/permissions.js.map +1 -1
- package/dist/core/tools/task.d.ts.map +1 -1
- package/dist/core/tools/task.js +68 -24
- package/dist/core/tools/task.js.map +1 -1
- package/dist/core/tools/tool-search.d.ts +24 -0
- package/dist/core/tools/tool-search.d.ts.map +1 -0
- package/dist/core/tools/tool-search.js +85 -0
- package/dist/core/tools/tool-search.js.map +1 -0
- package/dist/core/tools/tool-suggest.d.ts +18 -0
- package/dist/core/tools/tool-suggest.d.ts.map +1 -0
- package/dist/core/tools/tool-suggest.js +94 -0
- package/dist/core/tools/tool-suggest.js.map +1 -0
- package/dist/core/tools/verification-runner.d.ts.map +1 -1
- package/dist/core/tools/verification-runner.js +15 -1
- package/dist/core/tools/verification-runner.js.map +1 -1
- package/dist/core/unified-exec.d.ts +39 -0
- package/dist/core/unified-exec.d.ts.map +1 -0
- package/dist/core/unified-exec.js +286 -0
- package/dist/core/unified-exec.js.map +1 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +93 -11
- package/dist/main.js.map +1 -1
- package/dist/modes/acp/acp-mode.d.ts +17 -0
- package/dist/modes/acp/acp-mode.d.ts.map +1 -0
- package/dist/modes/acp/acp-mode.js +352 -0
- package/dist/modes/acp/acp-mode.js.map +1 -0
- package/dist/modes/index.d.ts +2 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +1 -0
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +217 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +8 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +159 -72
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +25 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +33 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +13 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +189 -28
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +54 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +96 -9
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/README.md +2 -0
- package/docs/acp-rpc-mapping.md +38 -0
- package/docs/configuration.generated.md +81 -0
- package/docs/configuration.md +7 -0
- package/package.json +4 -1
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import stripAnsi from "strip-ansi";
|
|
4
|
+
import { getShellConfig, getShellEnv, killProcessTree, sanitizeBinaryOutput } from "../utils/shell.js";
|
|
5
|
+
const DEFAULT_YIELD_TIME_MS = 1000;
|
|
6
|
+
const MAX_YIELD_TIME_MS = 60_000;
|
|
7
|
+
const DEFAULT_MAX_OUTPUT_CHARS = 12_000;
|
|
8
|
+
const MAX_OUTPUT_CHARS = 250_000;
|
|
9
|
+
const MAX_PENDING_OUTPUT_CHARS = 1_000_000;
|
|
10
|
+
const FINISHED_SESSION_TTL_MS = 5 * 60_000;
|
|
11
|
+
const EXIT_GRACE_TIME_MS = 75;
|
|
12
|
+
const DEFAULT_PTY_BRIDGE_BIN = "python3";
|
|
13
|
+
const PYTHON_PTY_BRIDGE_SCRIPT = String.raw `import os
|
|
14
|
+
import pty
|
|
15
|
+
import select
|
|
16
|
+
import subprocess
|
|
17
|
+
import sys
|
|
18
|
+
|
|
19
|
+
if len(sys.argv) < 2:
|
|
20
|
+
print("pty bridge requires shell command arguments", file=sys.stderr)
|
|
21
|
+
sys.exit(2)
|
|
22
|
+
|
|
23
|
+
command = sys.argv[1:]
|
|
24
|
+
master_fd, slave_fd = pty.openpty()
|
|
25
|
+
child = subprocess.Popen(command, stdin=slave_fd, stdout=slave_fd, stderr=slave_fd)
|
|
26
|
+
os.close(slave_fd)
|
|
27
|
+
|
|
28
|
+
stdin_fd = sys.stdin.fileno()
|
|
29
|
+
stdout_fd = sys.stdout.fileno()
|
|
30
|
+
stdin_open = True
|
|
31
|
+
|
|
32
|
+
while True:
|
|
33
|
+
readers = [master_fd]
|
|
34
|
+
if stdin_open:
|
|
35
|
+
readers.append(stdin_fd)
|
|
36
|
+
readable, _, _ = select.select(readers, [], [], 0.05)
|
|
37
|
+
|
|
38
|
+
if master_fd in readable:
|
|
39
|
+
try:
|
|
40
|
+
chunk = os.read(master_fd, 4096)
|
|
41
|
+
except OSError:
|
|
42
|
+
chunk = b""
|
|
43
|
+
if chunk:
|
|
44
|
+
os.write(stdout_fd, chunk)
|
|
45
|
+
|
|
46
|
+
if stdin_open and stdin_fd in readable:
|
|
47
|
+
input_chunk = os.read(stdin_fd, 4096)
|
|
48
|
+
if input_chunk:
|
|
49
|
+
os.write(master_fd, input_chunk)
|
|
50
|
+
else:
|
|
51
|
+
stdin_open = False
|
|
52
|
+
|
|
53
|
+
if child.poll() is not None:
|
|
54
|
+
while True:
|
|
55
|
+
try:
|
|
56
|
+
chunk = os.read(master_fd, 4096)
|
|
57
|
+
except OSError:
|
|
58
|
+
chunk = b""
|
|
59
|
+
if not chunk:
|
|
60
|
+
break
|
|
61
|
+
os.write(stdout_fd, chunk)
|
|
62
|
+
break
|
|
63
|
+
|
|
64
|
+
sys.exit(child.returncode if child.returncode is not None else 0)`;
|
|
65
|
+
function normalizeYieldTimeMs(value) {
|
|
66
|
+
if (typeof value !== "number" || Number.isNaN(value))
|
|
67
|
+
return DEFAULT_YIELD_TIME_MS;
|
|
68
|
+
return Math.max(0, Math.min(MAX_YIELD_TIME_MS, Math.floor(value)));
|
|
69
|
+
}
|
|
70
|
+
function normalizeMaxOutputChars(value) {
|
|
71
|
+
if (typeof value !== "number" || Number.isNaN(value))
|
|
72
|
+
return DEFAULT_MAX_OUTPUT_CHARS;
|
|
73
|
+
return Math.max(1, Math.min(MAX_OUTPUT_CHARS, Math.floor(value)));
|
|
74
|
+
}
|
|
75
|
+
export class UnifiedExecManager {
|
|
76
|
+
constructor() {
|
|
77
|
+
this.sessions = new Map();
|
|
78
|
+
this.nextSessionId = 1;
|
|
79
|
+
}
|
|
80
|
+
async execCommand(input) {
|
|
81
|
+
const command = input.command?.trim();
|
|
82
|
+
if (!command) {
|
|
83
|
+
throw new Error("exec_command requires a non-empty command.");
|
|
84
|
+
}
|
|
85
|
+
const session = this.createSession(command, input);
|
|
86
|
+
await this.waitForUpdate(session, normalizeYieldTimeMs(input.yieldTimeMs));
|
|
87
|
+
await this.waitForExitGrace(session);
|
|
88
|
+
return this.buildPollResult(session, normalizeMaxOutputChars(input.maxOutputChars));
|
|
89
|
+
}
|
|
90
|
+
async writeStdin(input) {
|
|
91
|
+
const session = this.sessions.get(input.sessionId);
|
|
92
|
+
if (!session) {
|
|
93
|
+
throw new Error(`exec session not found: ${input.sessionId}`);
|
|
94
|
+
}
|
|
95
|
+
if (input.chars && session.running) {
|
|
96
|
+
try {
|
|
97
|
+
session.child.stdin?.write(input.chars);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
throw new Error(`Failed to write to exec session ${input.sessionId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
await this.waitForUpdate(session, normalizeYieldTimeMs(input.yieldTimeMs));
|
|
104
|
+
await this.waitForExitGrace(session);
|
|
105
|
+
return this.buildPollResult(session, normalizeMaxOutputChars(input.maxOutputChars));
|
|
106
|
+
}
|
|
107
|
+
dispose() {
|
|
108
|
+
for (const session of this.sessions.values()) {
|
|
109
|
+
if (session.cleanupTimer) {
|
|
110
|
+
clearTimeout(session.cleanupTimer);
|
|
111
|
+
session.cleanupTimer = undefined;
|
|
112
|
+
}
|
|
113
|
+
if (session.running && session.child.pid) {
|
|
114
|
+
killProcessTree(session.child.pid);
|
|
115
|
+
}
|
|
116
|
+
session.waiters.clear();
|
|
117
|
+
}
|
|
118
|
+
this.sessions.clear();
|
|
119
|
+
}
|
|
120
|
+
createSession(command, input) {
|
|
121
|
+
const invocation = this.resolveInvocation(command, input);
|
|
122
|
+
const child = spawn(invocation.command, invocation.args, {
|
|
123
|
+
cwd: input.cwd ? resolve(input.cwd) : undefined,
|
|
124
|
+
env: getShellEnv(),
|
|
125
|
+
detached: true,
|
|
126
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
127
|
+
});
|
|
128
|
+
const session = {
|
|
129
|
+
id: this.nextSessionId++,
|
|
130
|
+
child,
|
|
131
|
+
usesPty: invocation.usesPty,
|
|
132
|
+
pendingOutput: [],
|
|
133
|
+
pendingChars: 0,
|
|
134
|
+
running: true,
|
|
135
|
+
exitCode: null,
|
|
136
|
+
waiters: new Set(),
|
|
137
|
+
};
|
|
138
|
+
this.sessions.set(session.id, session);
|
|
139
|
+
const stdoutDecoder = new TextDecoder();
|
|
140
|
+
const stderrDecoder = new TextDecoder();
|
|
141
|
+
const pushOutput = (raw, decoder) => {
|
|
142
|
+
let text = sanitizeBinaryOutput(stripAnsi(decoder.decode(raw, { stream: true }))).replace(/\r/g, "");
|
|
143
|
+
if (session.usesPty) {
|
|
144
|
+
text = text.replace(/\^D\x08\x08/g, "");
|
|
145
|
+
}
|
|
146
|
+
if (!text)
|
|
147
|
+
return;
|
|
148
|
+
this.appendOutput(session, text);
|
|
149
|
+
};
|
|
150
|
+
child.stdout?.on("data", (raw) => pushOutput(raw, stdoutDecoder));
|
|
151
|
+
child.stderr?.on("data", (raw) => pushOutput(raw, stderrDecoder));
|
|
152
|
+
child.on("error", (error) => {
|
|
153
|
+
this.appendOutput(session, `\n[exec error] ${error.message}\n`);
|
|
154
|
+
});
|
|
155
|
+
child.on("close", (code) => {
|
|
156
|
+
session.running = false;
|
|
157
|
+
session.exitCode = code ?? null;
|
|
158
|
+
this.notify(session);
|
|
159
|
+
session.cleanupTimer = setTimeout(() => {
|
|
160
|
+
this.sessions.delete(session.id);
|
|
161
|
+
}, FINISHED_SESSION_TTL_MS);
|
|
162
|
+
session.cleanupTimer.unref();
|
|
163
|
+
});
|
|
164
|
+
return session;
|
|
165
|
+
}
|
|
166
|
+
appendOutput(session, chunk) {
|
|
167
|
+
session.pendingOutput.push(chunk);
|
|
168
|
+
session.pendingChars += chunk.length;
|
|
169
|
+
while (session.pendingChars > MAX_PENDING_OUTPUT_CHARS && session.pendingOutput.length > 1) {
|
|
170
|
+
const removed = session.pendingOutput.shift();
|
|
171
|
+
if (!removed)
|
|
172
|
+
break;
|
|
173
|
+
session.pendingChars -= removed.length;
|
|
174
|
+
}
|
|
175
|
+
this.notify(session);
|
|
176
|
+
}
|
|
177
|
+
notify(session) {
|
|
178
|
+
if (session.waiters.size === 0)
|
|
179
|
+
return;
|
|
180
|
+
const waiters = Array.from(session.waiters);
|
|
181
|
+
session.waiters.clear();
|
|
182
|
+
for (const resolveWaiter of waiters) {
|
|
183
|
+
resolveWaiter();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async waitForUpdate(session, timeoutMs) {
|
|
187
|
+
if (!session.running || session.pendingChars > 0 || timeoutMs <= 0) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
await new Promise((resolveWait) => {
|
|
191
|
+
const onUpdate = () => {
|
|
192
|
+
if (timer)
|
|
193
|
+
clearTimeout(timer);
|
|
194
|
+
resolveWait();
|
|
195
|
+
};
|
|
196
|
+
const timer = setTimeout(() => {
|
|
197
|
+
session.waiters.delete(onUpdate);
|
|
198
|
+
resolveWait();
|
|
199
|
+
}, timeoutMs);
|
|
200
|
+
session.waiters.add(onUpdate);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
async waitForExitGrace(session) {
|
|
204
|
+
if (!session.running)
|
|
205
|
+
return;
|
|
206
|
+
await this.waitForClose(session, EXIT_GRACE_TIME_MS);
|
|
207
|
+
}
|
|
208
|
+
async waitForClose(session, timeoutMs) {
|
|
209
|
+
if (!session.running || timeoutMs <= 0)
|
|
210
|
+
return;
|
|
211
|
+
await new Promise((resolveWait) => {
|
|
212
|
+
const onUpdate = () => {
|
|
213
|
+
if (!session.running) {
|
|
214
|
+
if (timer)
|
|
215
|
+
clearTimeout(timer);
|
|
216
|
+
session.waiters.delete(onUpdate);
|
|
217
|
+
resolveWait();
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
const timer = setTimeout(() => {
|
|
221
|
+
session.waiters.delete(onUpdate);
|
|
222
|
+
resolveWait();
|
|
223
|
+
}, timeoutMs);
|
|
224
|
+
session.waiters.add(onUpdate);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
drainOutput(session, maxOutputChars) {
|
|
228
|
+
const combined = session.pendingOutput.join("");
|
|
229
|
+
session.pendingOutput = [];
|
|
230
|
+
session.pendingChars = 0;
|
|
231
|
+
if (combined.length <= maxOutputChars)
|
|
232
|
+
return combined;
|
|
233
|
+
return combined.slice(combined.length - maxOutputChars);
|
|
234
|
+
}
|
|
235
|
+
buildPollResult(session, maxOutputChars) {
|
|
236
|
+
const output = this.drainOutput(session, maxOutputChars);
|
|
237
|
+
if (session.running) {
|
|
238
|
+
return {
|
|
239
|
+
output,
|
|
240
|
+
running: true,
|
|
241
|
+
sessionId: session.id,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
if (session.cleanupTimer) {
|
|
245
|
+
clearTimeout(session.cleanupTimer);
|
|
246
|
+
session.cleanupTimer = undefined;
|
|
247
|
+
}
|
|
248
|
+
this.sessions.delete(session.id);
|
|
249
|
+
return {
|
|
250
|
+
output,
|
|
251
|
+
running: false,
|
|
252
|
+
exitCode: session.exitCode,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
resolveInvocation(command, input) {
|
|
256
|
+
const shellConfig = getShellConfig();
|
|
257
|
+
const shell = typeof input.shell === "string" && input.shell.trim().length > 0 ? input.shell.trim() : shellConfig.shell;
|
|
258
|
+
const shellArgs = this.buildShellArgs(command, input.login, shellConfig.args);
|
|
259
|
+
if (!input.tty) {
|
|
260
|
+
return {
|
|
261
|
+
command: shell,
|
|
262
|
+
args: shellArgs,
|
|
263
|
+
usesPty: false,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
if (process.platform === "win32") {
|
|
267
|
+
throw new Error("exec_command tty=true is not supported on Windows.");
|
|
268
|
+
}
|
|
269
|
+
const ptyBridgeBin = process.env.IOSM_EXEC_PTY_BRIDGE_BIN?.trim() || DEFAULT_PTY_BRIDGE_BIN;
|
|
270
|
+
return {
|
|
271
|
+
command: ptyBridgeBin,
|
|
272
|
+
args: ["-u", "-c", PYTHON_PTY_BRIDGE_SCRIPT, shell, ...shellArgs],
|
|
273
|
+
usesPty: true,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
buildShellArgs(command, login, defaultArgs) {
|
|
277
|
+
if (login === true) {
|
|
278
|
+
return ["-l", "-c", command];
|
|
279
|
+
}
|
|
280
|
+
if (login === false) {
|
|
281
|
+
return ["-c", command];
|
|
282
|
+
}
|
|
283
|
+
return [...defaultArgs, command];
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=unified-exec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unified-exec.js","sourceRoot":"","sources":["../../src/core/unified-exec.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, type ChildProcess } from \"node:child_process\";\nimport { resolve } from \"node:path\";\nimport stripAnsi from \"strip-ansi\";\nimport { getShellConfig, getShellEnv, killProcessTree, sanitizeBinaryOutput } from \"../utils/shell.js\";\n\nconst DEFAULT_YIELD_TIME_MS = 1000;\nconst MAX_YIELD_TIME_MS = 60_000;\nconst DEFAULT_MAX_OUTPUT_CHARS = 12_000;\nconst MAX_OUTPUT_CHARS = 250_000;\nconst MAX_PENDING_OUTPUT_CHARS = 1_000_000;\nconst FINISHED_SESSION_TTL_MS = 5 * 60_000;\nconst EXIT_GRACE_TIME_MS = 75;\nconst DEFAULT_PTY_BRIDGE_BIN = \"python3\";\n\nconst PYTHON_PTY_BRIDGE_SCRIPT = String.raw`import os\nimport pty\nimport select\nimport subprocess\nimport sys\n\nif len(sys.argv) < 2:\n\tprint(\"pty bridge requires shell command arguments\", file=sys.stderr)\n\tsys.exit(2)\n\ncommand = sys.argv[1:]\nmaster_fd, slave_fd = pty.openpty()\nchild = subprocess.Popen(command, stdin=slave_fd, stdout=slave_fd, stderr=slave_fd)\nos.close(slave_fd)\n\nstdin_fd = sys.stdin.fileno()\nstdout_fd = sys.stdout.fileno()\nstdin_open = True\n\nwhile True:\n\treaders = [master_fd]\n\tif stdin_open:\n\t\treaders.append(stdin_fd)\n\treadable, _, _ = select.select(readers, [], [], 0.05)\n\n\tif master_fd in readable:\n\t\ttry:\n\t\t\tchunk = os.read(master_fd, 4096)\n\t\texcept OSError:\n\t\t\tchunk = b\"\"\n\t\tif chunk:\n\t\t\tos.write(stdout_fd, chunk)\n\n\tif stdin_open and stdin_fd in readable:\n\t\tinput_chunk = os.read(stdin_fd, 4096)\n\t\tif input_chunk:\n\t\t\tos.write(master_fd, input_chunk)\n\t\telse:\n\t\t\tstdin_open = False\n\n\tif child.poll() is not None:\n\t\twhile True:\n\t\t\ttry:\n\t\t\t\tchunk = os.read(master_fd, 4096)\n\t\t\texcept OSError:\n\t\t\t\tchunk = b\"\"\n\t\t\tif not chunk:\n\t\t\t\tbreak\n\t\t\tos.write(stdout_fd, chunk)\n\t\tbreak\n\nsys.exit(child.returncode if child.returncode is not None else 0)`;\n\nexport interface UnifiedExecRunInput {\n\tcommand: string;\n\tcwd?: string;\n\ttty?: boolean;\n\tshell?: string;\n\tlogin?: boolean;\n\tyieldTimeMs?: number;\n\tmaxOutputChars?: number;\n}\n\nexport interface UnifiedExecWriteInput {\n\tsessionId: number;\n\tchars?: string;\n\tyieldTimeMs?: number;\n\tmaxOutputChars?: number;\n}\n\nexport interface UnifiedExecPollResult {\n\toutput: string;\n\trunning: boolean;\n\tsessionId?: number;\n\texitCode?: number | null;\n}\n\ninterface UnifiedExecSession {\n\tid: number;\n\tchild: ChildProcess;\n\tusesPty: boolean;\n\tpendingOutput: string[];\n\tpendingChars: number;\n\trunning: boolean;\n\texitCode: number | null;\n\twaiters: Set<() => void>;\n\tcleanupTimer?: NodeJS.Timeout;\n}\n\nfunction normalizeYieldTimeMs(value: number | undefined): number {\n\tif (typeof value !== \"number\" || Number.isNaN(value)) return DEFAULT_YIELD_TIME_MS;\n\treturn Math.max(0, Math.min(MAX_YIELD_TIME_MS, Math.floor(value)));\n}\n\nfunction normalizeMaxOutputChars(value: number | undefined): number {\n\tif (typeof value !== \"number\" || Number.isNaN(value)) return DEFAULT_MAX_OUTPUT_CHARS;\n\treturn Math.max(1, Math.min(MAX_OUTPUT_CHARS, Math.floor(value)));\n}\n\nexport class UnifiedExecManager {\n\tprivate sessions = new Map<number, UnifiedExecSession>();\n\tprivate nextSessionId = 1;\n\n\tasync execCommand(input: UnifiedExecRunInput): Promise<UnifiedExecPollResult> {\n\t\tconst command = input.command?.trim();\n\t\tif (!command) {\n\t\t\tthrow new Error(\"exec_command requires a non-empty command.\");\n\t\t}\n\n\t\tconst session = this.createSession(command, input);\n\t\tawait this.waitForUpdate(session, normalizeYieldTimeMs(input.yieldTimeMs));\n\t\tawait this.waitForExitGrace(session);\n\t\treturn this.buildPollResult(session, normalizeMaxOutputChars(input.maxOutputChars));\n\t}\n\n\tasync writeStdin(input: UnifiedExecWriteInput): Promise<UnifiedExecPollResult> {\n\t\tconst session = this.sessions.get(input.sessionId);\n\t\tif (!session) {\n\t\t\tthrow new Error(`exec session not found: ${input.sessionId}`);\n\t\t}\n\n\t\tif (input.chars && session.running) {\n\t\t\ttry {\n\t\t\t\tsession.child.stdin?.write(input.chars);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(`Failed to write to exec session ${input.sessionId}: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t}\n\n\t\tawait this.waitForUpdate(session, normalizeYieldTimeMs(input.yieldTimeMs));\n\t\tawait this.waitForExitGrace(session);\n\t\treturn this.buildPollResult(session, normalizeMaxOutputChars(input.maxOutputChars));\n\t}\n\n\tdispose(): void {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tif (session.cleanupTimer) {\n\t\t\t\tclearTimeout(session.cleanupTimer);\n\t\t\t\tsession.cleanupTimer = undefined;\n\t\t\t}\n\t\t\tif (session.running && session.child.pid) {\n\t\t\t\tkillProcessTree(session.child.pid);\n\t\t\t}\n\t\t\tsession.waiters.clear();\n\t\t}\n\t\tthis.sessions.clear();\n\t}\n\n\tprivate createSession(command: string, input: UnifiedExecRunInput): UnifiedExecSession {\n\t\tconst invocation = this.resolveInvocation(command, input);\n\t\tconst child = spawn(invocation.command, invocation.args, {\n\t\t\tcwd: input.cwd ? resolve(input.cwd) : undefined,\n\t\t\tenv: getShellEnv(),\n\t\t\tdetached: true,\n\t\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t\t});\n\n\t\tconst session: UnifiedExecSession = {\n\t\t\tid: this.nextSessionId++,\n\t\t\tchild,\n\t\t\tusesPty: invocation.usesPty,\n\t\t\tpendingOutput: [],\n\t\t\tpendingChars: 0,\n\t\t\trunning: true,\n\t\t\texitCode: null,\n\t\t\twaiters: new Set(),\n\t\t};\n\t\tthis.sessions.set(session.id, session);\n\n\t\tconst stdoutDecoder = new TextDecoder();\n\t\tconst stderrDecoder = new TextDecoder();\n\t\tconst pushOutput = (raw: Buffer, decoder: InstanceType<typeof TextDecoder>): void => {\n\t\t\tlet text = sanitizeBinaryOutput(stripAnsi(decoder.decode(raw, { stream: true }))).replace(/\\r/g, \"\");\n\t\t\tif (session.usesPty) {\n\t\t\t\ttext = text.replace(/\\^D\\x08\\x08/g, \"\");\n\t\t\t}\n\t\t\tif (!text) return;\n\t\t\tthis.appendOutput(session, text);\n\t\t};\n\n\t\tchild.stdout?.on(\"data\", (raw: Buffer) => pushOutput(raw, stdoutDecoder));\n\t\tchild.stderr?.on(\"data\", (raw: Buffer) => pushOutput(raw, stderrDecoder));\n\t\tchild.on(\"error\", (error) => {\n\t\t\tthis.appendOutput(session, `\\n[exec error] ${error.message}\\n`);\n\t\t});\n\t\tchild.on(\"close\", (code) => {\n\t\t\tsession.running = false;\n\t\t\tsession.exitCode = code ?? null;\n\t\t\tthis.notify(session);\n\t\t\tsession.cleanupTimer = setTimeout(() => {\n\t\t\t\tthis.sessions.delete(session.id);\n\t\t\t}, FINISHED_SESSION_TTL_MS);\n\t\t\tsession.cleanupTimer.unref();\n\t\t});\n\n\t\treturn session;\n\t}\n\n\tprivate appendOutput(session: UnifiedExecSession, chunk: string): void {\n\t\tsession.pendingOutput.push(chunk);\n\t\tsession.pendingChars += chunk.length;\n\t\twhile (session.pendingChars > MAX_PENDING_OUTPUT_CHARS && session.pendingOutput.length > 1) {\n\t\t\tconst removed = session.pendingOutput.shift();\n\t\t\tif (!removed) break;\n\t\t\tsession.pendingChars -= removed.length;\n\t\t}\n\t\tthis.notify(session);\n\t}\n\n\tprivate notify(session: UnifiedExecSession): void {\n\t\tif (session.waiters.size === 0) return;\n\t\tconst waiters = Array.from(session.waiters);\n\t\tsession.waiters.clear();\n\t\tfor (const resolveWaiter of waiters) {\n\t\t\tresolveWaiter();\n\t\t}\n\t}\n\n\tprivate async waitForUpdate(session: UnifiedExecSession, timeoutMs: number): Promise<void> {\n\t\tif (!session.running || session.pendingChars > 0 || timeoutMs <= 0) {\n\t\t\treturn;\n\t\t}\n\t\tawait new Promise<void>((resolveWait) => {\n\t\t\tconst onUpdate = () => {\n\t\t\t\tif (timer) clearTimeout(timer);\n\t\t\t\tresolveWait();\n\t\t\t};\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsession.waiters.delete(onUpdate);\n\t\t\t\tresolveWait();\n\t\t\t}, timeoutMs);\n\t\t\tsession.waiters.add(onUpdate);\n\t\t});\n\t}\n\n\tprivate async waitForExitGrace(session: UnifiedExecSession): Promise<void> {\n\t\tif (!session.running) return;\n\t\tawait this.waitForClose(session, EXIT_GRACE_TIME_MS);\n\t}\n\n\tprivate async waitForClose(session: UnifiedExecSession, timeoutMs: number): Promise<void> {\n\t\tif (!session.running || timeoutMs <= 0) return;\n\t\tawait new Promise<void>((resolveWait) => {\n\t\t\tconst onUpdate = () => {\n\t\t\t\tif (!session.running) {\n\t\t\t\t\tif (timer) clearTimeout(timer);\n\t\t\t\t\tsession.waiters.delete(onUpdate);\n\t\t\t\t\tresolveWait();\n\t\t\t\t}\n\t\t\t};\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsession.waiters.delete(onUpdate);\n\t\t\t\tresolveWait();\n\t\t\t}, timeoutMs);\n\t\t\tsession.waiters.add(onUpdate);\n\t\t});\n\t}\n\n\tprivate drainOutput(session: UnifiedExecSession, maxOutputChars: number): string {\n\t\tconst combined = session.pendingOutput.join(\"\");\n\t\tsession.pendingOutput = [];\n\t\tsession.pendingChars = 0;\n\t\tif (combined.length <= maxOutputChars) return combined;\n\t\treturn combined.slice(combined.length - maxOutputChars);\n\t}\n\n\tprivate buildPollResult(session: UnifiedExecSession, maxOutputChars: number): UnifiedExecPollResult {\n\t\tconst output = this.drainOutput(session, maxOutputChars);\n\t\tif (session.running) {\n\t\t\treturn {\n\t\t\t\toutput,\n\t\t\t\trunning: true,\n\t\t\t\tsessionId: session.id,\n\t\t\t};\n\t\t}\n\t\tif (session.cleanupTimer) {\n\t\t\tclearTimeout(session.cleanupTimer);\n\t\t\tsession.cleanupTimer = undefined;\n\t\t}\n\t\tthis.sessions.delete(session.id);\n\t\treturn {\n\t\t\toutput,\n\t\t\trunning: false,\n\t\t\texitCode: session.exitCode,\n\t\t};\n\t}\n\n\tprivate resolveInvocation(\n\t\tcommand: string,\n\t\tinput: UnifiedExecRunInput,\n\t): { command: string; args: string[]; usesPty: boolean } {\n\t\tconst shellConfig = getShellConfig();\n\t\tconst shell = typeof input.shell === \"string\" && input.shell.trim().length > 0 ? input.shell.trim() : shellConfig.shell;\n\t\tconst shellArgs = this.buildShellArgs(command, input.login, shellConfig.args);\n\n\t\tif (!input.tty) {\n\t\t\treturn {\n\t\t\t\tcommand: shell,\n\t\t\t\targs: shellArgs,\n\t\t\t\tusesPty: false,\n\t\t\t};\n\t\t}\n\n\t\tif (process.platform === \"win32\") {\n\t\t\tthrow new Error(\"exec_command tty=true is not supported on Windows.\");\n\t\t}\n\n\t\tconst ptyBridgeBin = process.env.IOSM_EXEC_PTY_BRIDGE_BIN?.trim() || DEFAULT_PTY_BRIDGE_BIN;\n\t\treturn {\n\t\t\tcommand: ptyBridgeBin,\n\t\t\targs: [\"-u\", \"-c\", PYTHON_PTY_BRIDGE_SCRIPT, shell, ...shellArgs],\n\t\t\tusesPty: true,\n\t\t};\n\t}\n\n\tprivate buildShellArgs(command: string, login: boolean | undefined, defaultArgs: string[]): string[] {\n\t\tif (login === true) {\n\t\t\treturn [\"-l\", \"-c\", command];\n\t\t}\n\t\tif (login === false) {\n\t\t\treturn [\"-c\", command];\n\t\t}\n\t\treturn [...defaultArgs, command];\n\t}\n}\n"]}
|
package/dist/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2uDH,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,iBAmUxC"}
|
package/dist/main.js
CHANGED
|
@@ -24,6 +24,7 @@ import { loadModelsDevProviderCatalog } from "./core/models-dev-provider-catalog
|
|
|
24
24
|
import { getMcpCommandHelp, getMergedServerByName, loadMergedMcpConfig, McpRuntime, parseMcpAddCommand, parseMcpTargetCommand, } from "./core/mcp/index.js";
|
|
25
25
|
import { getSemanticCommandHelp, parseSemanticCliCommand, SemanticConfigMissingError, SemanticIndexRequiredError, SemanticRebuildRequiredError, SemanticSearchRuntime, } from "./core/semantic/index.js";
|
|
26
26
|
import { DefaultPackageManager } from "./core/package-manager.js";
|
|
27
|
+
import { PolicyEngineV2 } from "./core/policy/index.js";
|
|
27
28
|
import { DefaultResourceLoader } from "./core/resource-loader.js";
|
|
28
29
|
import { createAgentSession } from "./core/sdk.js";
|
|
29
30
|
import { getProfileNames, isValidProfileName } from "./core/agent-profiles.js";
|
|
@@ -32,7 +33,7 @@ import { SettingsManager } from "./core/settings-manager.js";
|
|
|
32
33
|
import { printTimings, time } from "./core/timings.js";
|
|
33
34
|
import { allTools } from "./core/tools/index.js";
|
|
34
35
|
import { runMigrations, showDeprecationWarnings } from "./migrations.js";
|
|
35
|
-
import { InteractiveMode, runPrintMode, runRpcMode, runTelegramBridgeMode } from "./modes/index.js";
|
|
36
|
+
import { InteractiveMode, runAcpMode, runPrintMode, runRpcMode, runTelegramBridgeMode } from "./modes/index.js";
|
|
36
37
|
import { initTheme, stopThemeWatcher } from "./modes/interactive/theme/theme.js";
|
|
37
38
|
import { buildIosmAgentVerificationPrompt, buildIosmGuideAuthoringPrompt, buildIosmPriorityChecklist, createMetricSnapshot, extractAssistantText, formatMetricSnapshot, getIosmGuidePath, initIosmWorkspace, inspectIosmCycle, listIosmCycles, planIosmCycle, readIosmCycleReport, recordIosmCycleHistory, normalizeIosmGuideMarkdown, writeIosmGuideDocument, } from "./iosm/index.js";
|
|
38
39
|
/**
|
|
@@ -199,6 +200,7 @@ Install a package and add it to settings.
|
|
|
199
200
|
|
|
200
201
|
Options:
|
|
201
202
|
-l, --local Install project-locally (${CONFIG_DIR_NAME}/settings.json)
|
|
203
|
+
--yes-trust Non-interactive trust override for source/integrity checks
|
|
202
204
|
|
|
203
205
|
Examples:
|
|
204
206
|
${APP_NAME} install npm:@foo/bar
|
|
@@ -228,6 +230,9 @@ Example:
|
|
|
228
230
|
|
|
229
231
|
Update installed packages.
|
|
230
232
|
If <source> is provided, only that package is updated.
|
|
233
|
+
|
|
234
|
+
Options:
|
|
235
|
+
--yes-trust Non-interactive trust override for source/integrity checks
|
|
231
236
|
`);
|
|
232
237
|
return;
|
|
233
238
|
case "list":
|
|
@@ -246,6 +251,7 @@ function parsePackageCommand(args) {
|
|
|
246
251
|
}
|
|
247
252
|
let local = false;
|
|
248
253
|
let help = false;
|
|
254
|
+
let yesTrust = false;
|
|
249
255
|
let invalidOption;
|
|
250
256
|
let source;
|
|
251
257
|
for (const arg of rest) {
|
|
@@ -262,6 +268,10 @@ function parsePackageCommand(args) {
|
|
|
262
268
|
}
|
|
263
269
|
continue;
|
|
264
270
|
}
|
|
271
|
+
if (arg === "--yes-trust") {
|
|
272
|
+
yesTrust = true;
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
265
275
|
if (arg.startsWith("-")) {
|
|
266
276
|
invalidOption = invalidOption ?? arg;
|
|
267
277
|
continue;
|
|
@@ -270,7 +280,26 @@ function parsePackageCommand(args) {
|
|
|
270
280
|
source = arg;
|
|
271
281
|
}
|
|
272
282
|
}
|
|
273
|
-
return { command, source, local, help, invalidOption };
|
|
283
|
+
return { command, source, local, help, yesTrust, invalidOption };
|
|
284
|
+
}
|
|
285
|
+
async function requestTrustConsentFromTerminal(question) {
|
|
286
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
const rl = createInterface({
|
|
290
|
+
input: process.stdin,
|
|
291
|
+
output: process.stdout,
|
|
292
|
+
});
|
|
293
|
+
try {
|
|
294
|
+
const answer = await new Promise((resolve) => {
|
|
295
|
+
rl.question(`${question} [y/N] `, resolve);
|
|
296
|
+
});
|
|
297
|
+
const normalized = answer.trim().toLowerCase();
|
|
298
|
+
return normalized === "y" || normalized === "yes";
|
|
299
|
+
}
|
|
300
|
+
finally {
|
|
301
|
+
rl.close();
|
|
302
|
+
}
|
|
274
303
|
}
|
|
275
304
|
async function handlePackageCommand(args) {
|
|
276
305
|
const options = parsePackageCommand(args);
|
|
@@ -298,7 +327,25 @@ async function handlePackageCommand(args) {
|
|
|
298
327
|
const agentDir = getAgentDir();
|
|
299
328
|
const settingsManager = SettingsManager.create(cwd, agentDir);
|
|
300
329
|
reportSettingsErrors(settingsManager, "package command");
|
|
301
|
-
const
|
|
330
|
+
const policyEngine = new PolicyEngineV2({ cwd, agentDir, settingsManager });
|
|
331
|
+
const packageManager = new DefaultPackageManager({
|
|
332
|
+
cwd,
|
|
333
|
+
agentDir,
|
|
334
|
+
settingsManager,
|
|
335
|
+
allowedSourceHosts: policyEngine.getAllowedSourceHosts(),
|
|
336
|
+
allowNonInteractiveTrustOverride: options.yesTrust,
|
|
337
|
+
trustConsentProvider: async (request) => {
|
|
338
|
+
if (options.yesTrust)
|
|
339
|
+
return true;
|
|
340
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
const reasonLabel = request.reason === "fingerprint-change"
|
|
344
|
+
? `fingerprint changed (${request.previousFingerprint ?? "unknown"} -> ${request.fingerprint})`
|
|
345
|
+
: `new source fingerprint ${request.fingerprint}`;
|
|
346
|
+
return requestTrustConsentFromTerminal(`Trust ${request.sourceType} source "${request.source}" on host ${request.host} (${reasonLabel})?`);
|
|
347
|
+
},
|
|
348
|
+
});
|
|
302
349
|
packageManager.setProgressCallback((event) => {
|
|
303
350
|
if (event.type === "start") {
|
|
304
351
|
process.stdout.write(chalk.dim(`${event.message}\n`));
|
|
@@ -1113,7 +1160,19 @@ async function handleConfigCommand(args) {
|
|
|
1113
1160
|
const agentDir = getAgentDir();
|
|
1114
1161
|
const settingsManager = SettingsManager.create(cwd, agentDir);
|
|
1115
1162
|
reportSettingsErrors(settingsManager, "config command");
|
|
1116
|
-
const
|
|
1163
|
+
const policyEngine = new PolicyEngineV2({ cwd, agentDir, settingsManager });
|
|
1164
|
+
const packageManager = new DefaultPackageManager({
|
|
1165
|
+
cwd,
|
|
1166
|
+
agentDir,
|
|
1167
|
+
settingsManager,
|
|
1168
|
+
allowedSourceHosts: policyEngine.getAllowedSourceHosts(),
|
|
1169
|
+
trustConsentProvider: async (request) => {
|
|
1170
|
+
const reasonLabel = request.reason === "fingerprint-change"
|
|
1171
|
+
? `fingerprint changed (${request.previousFingerprint ?? "unknown"} -> ${request.fingerprint})`
|
|
1172
|
+
: `new source fingerprint ${request.fingerprint}`;
|
|
1173
|
+
return requestTrustConsentFromTerminal(`Trust ${request.sourceType} source "${request.source}" on host ${request.host} (${reasonLabel})?`);
|
|
1174
|
+
},
|
|
1175
|
+
});
|
|
1117
1176
|
const resolvedPaths = await packageManager.resolve();
|
|
1118
1177
|
await selectConfig({
|
|
1119
1178
|
resolvedPaths,
|
|
@@ -1487,6 +1546,7 @@ export async function main(args) {
|
|
|
1487
1546
|
const agentDir = getAgentDir();
|
|
1488
1547
|
const settingsManager = SettingsManager.create(cwd, agentDir);
|
|
1489
1548
|
reportSettingsErrors(settingsManager, "startup");
|
|
1549
|
+
const policyEngine = new PolicyEngineV2({ cwd, agentDir, settingsManager });
|
|
1490
1550
|
const authStorage = AuthStorage.create();
|
|
1491
1551
|
const modelRegistry = new ModelRegistry(authStorage, getModelsPath());
|
|
1492
1552
|
await hydrateAuthenticatedProviderModelsOnStartup(modelRegistry);
|
|
@@ -1552,8 +1612,8 @@ export async function main(args) {
|
|
|
1552
1612
|
});
|
|
1553
1613
|
return;
|
|
1554
1614
|
}
|
|
1555
|
-
// Read piped stdin content (if any) - skip for RPC
|
|
1556
|
-
if (parsed.mode !== "rpc") {
|
|
1615
|
+
// Read piped stdin content (if any) - skip for RPC/ACP modes which use stdin for protocol transport
|
|
1616
|
+
if (parsed.mode !== "rpc" && parsed.mode !== "acp") {
|
|
1557
1617
|
const stdinContent = await readPipedStdin();
|
|
1558
1618
|
if (stdinContent !== undefined) {
|
|
1559
1619
|
// Force print mode since interactive mode requires a TTY for keyboard input
|
|
@@ -1576,13 +1636,15 @@ export async function main(args) {
|
|
|
1576
1636
|
console.log(`Exported to: ${result}`);
|
|
1577
1637
|
process.exit(0);
|
|
1578
1638
|
}
|
|
1579
|
-
if (parsed.mode === "rpc" && parsed.fileArgs.length > 0) {
|
|
1580
|
-
console.error(chalk.red("Error: @file arguments are not supported in RPC mode"));
|
|
1639
|
+
if ((parsed.mode === "rpc" || parsed.mode === "acp") && parsed.fileArgs.length > 0) {
|
|
1640
|
+
console.error(chalk.red("Error: @file arguments are not supported in RPC/ACP mode"));
|
|
1581
1641
|
process.exit(1);
|
|
1582
1642
|
}
|
|
1583
1643
|
const { initialMessage, initialImages } = await prepareInitialMessage(parsed, settingsManager.getImageAutoResize());
|
|
1584
1644
|
const isInteractive = !parsed.print && parsed.mode === undefined;
|
|
1585
1645
|
const mode = parsed.mode || "text";
|
|
1646
|
+
const sandboxEnabled = parsed.sandbox ?? settingsManager.getSandboxEnabled();
|
|
1647
|
+
process.env.IOSM_SANDBOX_ENABLED = sandboxEnabled ? "1" : "0";
|
|
1586
1648
|
initTheme(settingsManager.getTheme(), isInteractive);
|
|
1587
1649
|
// Show deprecation warnings in interactive mode
|
|
1588
1650
|
if (isInteractive && deprecationWarnings.length > 0) {
|
|
@@ -1611,7 +1673,7 @@ export async function main(args) {
|
|
|
1611
1673
|
sessionOptions.authStorage = authStorage;
|
|
1612
1674
|
sessionOptions.modelRegistry = modelRegistry;
|
|
1613
1675
|
sessionOptions.resourceLoader = resourceLoader;
|
|
1614
|
-
sessionOptions.enableAskUserTool = isInteractive || mode === "rpc";
|
|
1676
|
+
sessionOptions.enableAskUserTool = isInteractive || mode === "rpc" || mode === "acp";
|
|
1615
1677
|
// Handle CLI --api-key as runtime override (not persisted)
|
|
1616
1678
|
if (parsed.apiKey) {
|
|
1617
1679
|
if (!sessionOptions.model) {
|
|
@@ -1621,12 +1683,19 @@ export async function main(args) {
|
|
|
1621
1683
|
authStorage.setRuntimeApiKey(sessionOptions.model.provider, parsed.apiKey);
|
|
1622
1684
|
}
|
|
1623
1685
|
let mcpRuntime;
|
|
1686
|
+
let sessionTraceSink;
|
|
1624
1687
|
try {
|
|
1625
1688
|
mcpRuntime = new McpRuntime({
|
|
1626
1689
|
cwd,
|
|
1627
1690
|
agentDir,
|
|
1628
1691
|
clientName: APP_NAME,
|
|
1629
1692
|
clientVersion: VERSION,
|
|
1693
|
+
onPolicyDecision: (event) => {
|
|
1694
|
+
sessionTraceSink?.appendRuntimeTrace("policy_decision", {
|
|
1695
|
+
scope: "mcp",
|
|
1696
|
+
...event,
|
|
1697
|
+
});
|
|
1698
|
+
},
|
|
1630
1699
|
});
|
|
1631
1700
|
await mcpRuntime.refresh();
|
|
1632
1701
|
printMcpConfigWarnings(mcpRuntime.getErrors());
|
|
@@ -1635,9 +1704,10 @@ export async function main(args) {
|
|
|
1635
1704
|
sessionOptions.customTools = [...(sessionOptions.customTools ?? []), ...mcpTools];
|
|
1636
1705
|
}
|
|
1637
1706
|
const { session, modelFallbackMessage } = await createAgentSession(sessionOptions);
|
|
1707
|
+
sessionTraceSink = session;
|
|
1638
1708
|
// RPC mode must start even without a preselected model so remote clients
|
|
1639
1709
|
// (for example Telegram bridge) can choose one later via /model.
|
|
1640
|
-
if (!isInteractive && mode !== "rpc" && !session.model) {
|
|
1710
|
+
if (!isInteractive && mode !== "rpc" && mode !== "acp" && !session.model) {
|
|
1641
1711
|
console.error(chalk.red("No model selected."));
|
|
1642
1712
|
console.error(chalk.yellow("\nSelect one explicitly:"));
|
|
1643
1713
|
console.error(` ${APP_NAME} --provider <provider> --model <model-id> ...`);
|
|
@@ -1662,7 +1732,18 @@ export async function main(args) {
|
|
|
1662
1732
|
}
|
|
1663
1733
|
}
|
|
1664
1734
|
if (mode === "rpc") {
|
|
1665
|
-
await runRpcMode(session
|
|
1735
|
+
await runRpcMode(session, {
|
|
1736
|
+
mcpRuntime,
|
|
1737
|
+
policyEngine,
|
|
1738
|
+
profileName: sessionOptions.profile,
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1741
|
+
else if (mode === "acp") {
|
|
1742
|
+
await runAcpMode(session, {
|
|
1743
|
+
mcpRuntime,
|
|
1744
|
+
policyEngine,
|
|
1745
|
+
profileName: sessionOptions.profile,
|
|
1746
|
+
});
|
|
1666
1747
|
}
|
|
1667
1748
|
else if (isInteractive) {
|
|
1668
1749
|
if (scopedModels.length > 0 && (parsed.verbose || !settingsManager.getQuietStartup())) {
|
|
@@ -1685,6 +1766,7 @@ export async function main(args) {
|
|
|
1685
1766
|
planMode: parsed.plan,
|
|
1686
1767
|
profile: sessionOptions.profile,
|
|
1687
1768
|
mcpRuntime,
|
|
1769
|
+
policyEngine,
|
|
1688
1770
|
});
|
|
1689
1771
|
await mode.run();
|
|
1690
1772
|
}
|