@span-io/agent-link 0.2.0 → 0.2.1

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/dist/index.js CHANGED
@@ -135,6 +135,9 @@ function handleControl(message) {
135
135
  return;
136
136
  }
137
137
  const optionsArgs = [...(payload?.args || args.agentArgs)];
138
+ const promptMode = payload?.promptMode === "stdin" || payload?.promptMode === "args"
139
+ ? payload.promptMode
140
+ : undefined;
138
141
  const rawPrompt = payload?.prompt || "";
139
142
  const normalized = compactPrompt(rawPrompt, promptPolicy);
140
143
  if (normalized.action !== "none") {
@@ -148,7 +151,8 @@ function handleControl(message) {
148
151
  },
149
152
  prompt: normalized.prompt,
150
153
  optionsArgs,
151
- executablePath: agentCandidate.path
154
+ executablePath: agentCandidate.path,
155
+ promptModeOverride: promptMode,
152
156
  });
153
157
  activeAgents.set(agentId, proc);
154
158
  console.log(`[${new Date().toLocaleTimeString()}] Spawning agent: ${agentCandidate.name} (${targetModel || "default model"})`);
@@ -217,6 +221,7 @@ async function runRemoteCommand(payload, transport) {
217
221
  function setupAgentPiping(agentId, proc) {
218
222
  const rawFlushSize = Number.parseInt(process.env.AGENT_LINK_STREAM_FLUSH_CHARS ?? "16384", 10);
219
223
  const flushSize = Number.isFinite(rawFlushSize) && rawFlushSize > 0 ? rawFlushSize : 16384;
224
+ const echoStdio = process.env.AGENT_LINK_ECHO_STDIO === "1";
220
225
  const setupStream = (stream, name) => {
221
226
  if (!stream)
222
227
  return;
@@ -224,6 +229,15 @@ function setupAgentPiping(agentId, proc) {
224
229
  stream.setEncoding("utf8");
225
230
  const flushChunk = (chunk) => {
226
231
  if (chunk.length > 0) {
232
+ if (echoStdio) {
233
+ const prefix = `[agent-link][${agentId}][${name}] `;
234
+ const lines = chunk.split("\n");
235
+ for (const line of lines) {
236
+ if (line.length > 0) {
237
+ console.log(`${prefix}${line}`);
238
+ }
239
+ }
240
+ }
227
241
  transport.sendLog(agentId, name, chunk);
228
242
  }
229
243
  };
@@ -8,7 +8,64 @@ const DEFAULT_PROMPT_FLAG = "";
8
8
  const DEFAULT_TTY_MODE = "auto";
9
9
  const DEFAULT_TTY_TERM = "dumb";
10
10
  function splitArgs(raw) {
11
- return raw.trim() === "" ? [] : raw.trim().split(/\s+/g);
11
+ if (raw.trim() === "") {
12
+ return [];
13
+ }
14
+ const args = [];
15
+ let current = "";
16
+ let quote = null;
17
+ let escaped = false;
18
+ for (const char of raw) {
19
+ if (escaped) {
20
+ current += char;
21
+ escaped = false;
22
+ continue;
23
+ }
24
+ if (quote === "'") {
25
+ if (char === "'") {
26
+ quote = null;
27
+ }
28
+ else {
29
+ current += char;
30
+ }
31
+ continue;
32
+ }
33
+ if (quote === '"') {
34
+ if (char === '"') {
35
+ quote = null;
36
+ continue;
37
+ }
38
+ if (char === "\\") {
39
+ escaped = true;
40
+ continue;
41
+ }
42
+ current += char;
43
+ continue;
44
+ }
45
+ if (char === "'" || char === '"') {
46
+ quote = char;
47
+ continue;
48
+ }
49
+ if (char === "\\") {
50
+ escaped = true;
51
+ continue;
52
+ }
53
+ if (/\s/.test(char)) {
54
+ if (current !== "") {
55
+ args.push(current);
56
+ current = "";
57
+ }
58
+ continue;
59
+ }
60
+ current += char;
61
+ }
62
+ if (escaped) {
63
+ current += "\\";
64
+ }
65
+ if (current !== "") {
66
+ args.push(current);
67
+ }
68
+ return args;
12
69
  }
13
70
  function shellQuote(value) {
14
71
  // Simple single-quote wrapping for display purposes
@@ -121,7 +178,7 @@ export function buildCommand({ agent, prompt, optionsArgs = [], executablePath }
121
178
  const rawArgs = process.env.CODEX_ARGS ?? DEFAULT_CODEX_ARGS;
122
179
  const promptFlag = process.env.CODEX_PROMPT_FLAG ?? DEFAULT_PROMPT_FLAG;
123
180
  // Determine Prompt Mode
124
- const envPromptMode = process.env.CODEX_PROMPT_MODE === "stdin" ? "stdin" : "args";
181
+ const envPromptMode = process.env.CODEX_PROMPT_MODE === "args" ? "args" : "stdin";
125
182
  const promptMode = promptModeOverride ?? envPromptMode;
126
183
  const extraArgs = optionsArgs.filter((arg) => arg.trim() !== "");
127
184
  const args = splitArgs(rawArgs);
@@ -163,12 +220,12 @@ export function spawnAgentProcess(config) {
163
220
  const sanitizedOptions = optionsArgs;
164
221
  const allowedRoots = parseAllowedRoots();
165
222
  const spawnWithMode = (promptModeOverride) => {
166
- const { command, args, promptMode } = buildCommand({ ...config, optionsArgs: sanitizedOptions }, promptModeOverride);
223
+ const { command, args, promptMode } = buildCommand({ ...config, optionsArgs: sanitizedOptions }, promptModeOverride ?? config.promptModeOverride);
167
224
  // Ensure requested project/working directories exist before launching CLI.
168
225
  ensureDirectoriesExist(collectDirectoriesFromArgs(args), allowedRoots);
169
226
  const ttyMode = process.env.CODEX_TTY_MODE ?? DEFAULT_TTY_MODE;
170
227
  const hasExec = args.includes("exec");
171
- const useScriptWrapper = ttyMode === "script" || (ttyMode === "auto" && hasExec);
228
+ const useScriptWrapper = promptMode === "stdin" ? false : ttyMode === "script" || (ttyMode === "auto" && hasExec);
172
229
  const ttyTerm = process.env.CODEX_TTY_TERM ?? DEFAULT_TTY_TERM;
173
230
  const defaultCwd = process.cwd(); // Client uses current working dir
174
231
  const workingDir = process.env.CODEX_CWD ?? defaultCwd;
@@ -197,7 +254,8 @@ export function spawnAgentProcess(config) {
197
254
  }
198
255
  });
199
256
  if (promptMode === "stdin") {
200
- child.stdin?.write(config.prompt);
257
+ const promptPayload = config.prompt.endsWith("\n") ? config.prompt : `${config.prompt}\n`;
258
+ child.stdin?.write(promptPayload);
201
259
  child.stdin?.end();
202
260
  }
203
261
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@span-io/agent-link",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Secure bridge between Span (AI control plane) and local agent CLI tools.",
5
5
  "type": "module",
6
6
  "bin": {