u-foo 1.9.6 → 1.9.8

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/bin/ufoo.js CHANGED
@@ -29,13 +29,15 @@ async function main() {
29
29
  }
30
30
  if (cmd === "agent-runner") {
31
31
  const agentType = argv[1] || "codex";
32
- await runInternalRunner({ projectRoot: process.cwd(), agentType });
32
+ const extraArgs = argv.slice(2);
33
+ await runInternalRunner({ projectRoot: process.cwd(), agentType, extraArgs });
33
34
  return;
34
35
  }
35
36
  if (cmd === "agent-pty-runner") {
36
37
  const agentType = argv[1] || "codex";
38
+ const extraArgs = argv.slice(2);
37
39
  try {
38
- await runPtyRunner({ projectRoot: process.cwd(), agentType });
40
+ await runPtyRunner({ projectRoot: process.cwd(), agentType, extraArgs });
39
41
  } catch (err) {
40
42
  const normalized = String(agentType || "").trim().toLowerCase();
41
43
  if (normalized === "ufoo" || normalized === "ucode" || normalized === "ufoo-code") {
@@ -44,7 +46,7 @@ async function main() {
44
46
  // Fallback to headless runner if PTY is unavailable
45
47
  // eslint-disable-next-line no-console
46
48
  console.error(`[pty-runner] ${err.message || err}. Falling back to headless internal runner.`);
47
- await runInternalRunner({ projectRoot: process.cwd(), agentType });
49
+ await runInternalRunner({ projectRoot: process.cwd(), agentType, extraArgs });
48
50
  }
49
51
  return;
50
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "u-foo",
3
- "version": "1.9.6",
3
+ "version": "1.9.8",
4
4
  "description": "Multi-Agent Workspace Protocol. Just add u. claude → uclaude, codex → ucodex.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://ufoo.dev",
@@ -484,6 +484,10 @@ const DEFAULT_CODEX = {
484
484
 
485
485
  function buildArgs(backend, prompt, opts) {
486
486
  const args = [...(backend.args || [])];
487
+ const extraArgs = Array.isArray(opts.extraArgs) ? opts.extraArgs.filter(Boolean) : [];
488
+ if (extraArgs.length > 0) {
489
+ args.push(...extraArgs);
490
+ }
487
491
  if (opts.model && backend.modelArg) {
488
492
  args.push(backend.modelArg, opts.model);
489
493
  }
@@ -588,6 +592,7 @@ async function runCliAgent(params) {
588
592
  sessionId,
589
593
  systemPrompt: params.systemPrompt,
590
594
  disableSession: params.disableSession,
595
+ extraArgs: params.extraArgs,
591
596
  });
592
597
  if (backend === DEFAULT_CODEX && params.sandbox) {
593
598
  applySandboxOverride(args, params.sandbox);
@@ -642,6 +647,7 @@ async function runCliAgent(params) {
642
647
  sessionId,
643
648
  systemPrompt: params.systemPrompt,
644
649
  disableSession: params.disableSession,
650
+ extraArgs: params.extraArgs,
645
651
  },
646
652
  );
647
653
  retryArgs = retry.args;
@@ -96,7 +96,18 @@ function drainQueue(queueFile) {
96
96
  return content.split(/\r?\n/).filter(Boolean);
97
97
  }
98
98
 
99
- async function handleEvent(projectRoot, agentType, provider, model, subscriber, nickname, evt, cliSessionState, busSender) {
99
+ async function handleEvent(
100
+ projectRoot,
101
+ agentType,
102
+ provider,
103
+ model,
104
+ subscriber,
105
+ nickname,
106
+ evt,
107
+ cliSessionState,
108
+ busSender,
109
+ extraArgs = []
110
+ ) {
100
111
  if (!evt || !evt.data || !evt.data.message) return;
101
112
  const prompt = evt.data.message;
102
113
  const publisher = evt.publisher || "unknown";
@@ -118,6 +129,7 @@ async function handleEvent(projectRoot, agentType, provider, model, subscriber,
118
129
  sessionId: cliSessionState.cliSessionId,
119
130
  sandbox,
120
131
  cwd: projectRoot,
132
+ extraArgs,
121
133
  onStreamDelta: emitStreamDelta,
122
134
  });
123
135
 
@@ -136,6 +148,7 @@ async function handleEvent(projectRoot, agentType, provider, model, subscriber,
136
148
  sessionId: null, // Let runCliAgent generate new session
137
149
  sandbox,
138
150
  cwd: projectRoot,
151
+ extraArgs,
139
152
  onStreamDelta: emitStreamDelta,
140
153
  });
141
154
  }
@@ -175,7 +188,7 @@ async function handleEvent(projectRoot, agentType, provider, model, subscriber,
175
188
  await busSender.flush();
176
189
  }
177
190
 
178
- async function runInternalRunner({ projectRoot, agentType = "codex" }) {
191
+ async function runInternalRunner({ projectRoot, agentType = "codex", extraArgs = [] }) {
179
192
  // Internal runner 必须由 daemon 启动,UFOO_SUBSCRIBER_ID 应该已经设置
180
193
  const { subscriber, agentType: parsedAgentType, sessionId } = parseSubscriberId();
181
194
  const nickname = process.env.UFOO_NICKNAME || "";
@@ -280,7 +293,8 @@ async function runInternalRunner({ projectRoot, agentType = "codex" }) {
280
293
  nickname,
281
294
  evt,
282
295
  cliSessionState,
283
- busSender
296
+ busSender,
297
+ extraArgs
284
298
  );
285
299
  }
286
300
 
@@ -113,24 +113,25 @@ function buildPrompt(text, marker) {
113
113
  return `${text}\n\n请在完成后输出以下标记(单独一行):\n${marker}\n`;
114
114
  }
115
115
 
116
- function resolveCommand(agentType) {
116
+ function resolveCommand(agentType, extraArgs = []) {
117
117
  const normalizedAgent = String(agentType || "").trim().toLowerCase();
118
+ const extra = Array.isArray(extraArgs) ? extraArgs : [];
118
119
  const rawCmd = String(process.env.UFOO_PTY_CMD || "").trim();
119
120
  if (rawCmd) {
120
121
  const rawArgs = String(process.env.UFOO_PTY_ARGS || "").trim();
121
122
  const args = rawArgs ? rawArgs.split(/\s+/).filter(Boolean) : [];
122
- return { command: rawCmd, args };
123
+ return { command: rawCmd, args: [...args, ...extra] };
123
124
  }
124
125
  if (normalizedAgent === "claude" || normalizedAgent === "claude-code") {
125
- return { command: "claude", args: [] };
126
+ return { command: "claude", args: [...extra] };
126
127
  }
127
128
  if (normalizedAgent === "ufoo" || normalizedAgent === "ucode" || normalizedAgent === "ufoo-code") {
128
- return { command: "ucode", args: [] };
129
+ return { command: "ucode", args: [...extra] };
129
130
  }
130
- return { command: "codex", args: ["--no-alt-screen", "--sandbox", "workspace-write"] };
131
+ return { command: "codex", args: ["--no-alt-screen", "--sandbox", "workspace-write", ...extra] };
131
132
  }
132
133
 
133
- async function runPtyRunner({ projectRoot, agentType = "codex" }) {
134
+ async function runPtyRunner({ projectRoot, agentType = "codex", extraArgs = [] }) {
134
135
  let pty;
135
136
  try {
136
137
  // eslint-disable-next-line global-require
@@ -156,7 +157,7 @@ async function runPtyRunner({ projectRoot, agentType = "codex" }) {
156
157
  const logFile = path.join(runDir, "pty-runner.log");
157
158
  const injectSockPath = path.join(queueDir, "inject.sock");
158
159
 
159
- const { command, args } = resolveCommand(agentType);
160
+ const { command, args } = resolveCommand(agentType, extraArgs);
160
161
  const env = {
161
162
  ...process.env,
162
163
  UFOO_LAUNCH_MODE: "internal-pty",
@@ -1342,8 +1342,11 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
1342
1342
  : null,
1343
1343
  };
1344
1344
  let soloLaunchBootstrap = null;
1345
- if (requestedProfile && normalizedAgent === "ufoo") {
1346
- const soloNickname = explicitNickname || "ucode";
1345
+ if (requestedProfile && (normalizedAgent === "ufoo" || normalizedAgent === "claude" || normalizedAgent === "codex")) {
1346
+ const agentTypeMap = { ufoo: "ufoo-code", claude: "claude-code", codex: "codex" };
1347
+ const defaultNickMap = { ufoo: "ucode", claude: "claude", codex: "codex" };
1348
+ const agentTypeForBootstrap = agentTypeMap[normalizedAgent];
1349
+ const soloNickname = explicitNickname || defaultNickMap[normalizedAgent];
1347
1350
  const profileResult = resolveSoloPromptProfile(projectRoot, requestedProfile);
1348
1351
  if (!profileResult.ok) {
1349
1352
  socket.write(
@@ -1357,17 +1360,36 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
1357
1360
  }
1358
1361
  const built = buildSoloBootstrap({
1359
1362
  nickname: soloNickname,
1360
- agentType: "ufoo-code",
1363
+ agentType: agentTypeForBootstrap,
1361
1364
  requestedProfile: profileResult.requested_profile,
1362
1365
  profile: profileResult.profile,
1363
1366
  });
1364
1367
  if (built.required) {
1365
1368
  try {
1366
- const prepared = prepareSoloUcodeBootstrap(projectRoot, soloNickname, built.promptText);
1367
- op.extra_env = {
1368
- ...(op.extra_env && typeof op.extra_env === "object" ? op.extra_env : {}),
1369
- UFOO_UCODE_BOOTSTRAP_FILE: prepared.file,
1370
- };
1369
+ if (normalizedAgent === "ufoo") {
1370
+ // ucode: bootstrap via env var pointing to file
1371
+ const prepared = prepareSoloUcodeBootstrap(projectRoot, soloNickname, built.promptText);
1372
+ op.extra_env = {
1373
+ ...(op.extra_env && typeof op.extra_env === "object" ? op.extra_env : {}),
1374
+ UFOO_UCODE_BOOTSTRAP_FILE: prepared.file,
1375
+ };
1376
+ } else if (normalizedAgent === "claude") {
1377
+ // claude-code: bootstrap via --append-system-prompt file
1378
+ const bootstrapDir = path.join(getUfooPaths(projectRoot).agentDir, "claude-code", "solo");
1379
+ fs.mkdirSync(bootstrapDir, { recursive: true });
1380
+ const bootstrapFile = path.join(bootstrapDir, `${soloNickname}.bootstrap.md`);
1381
+ fs.writeFileSync(bootstrapFile, built.promptText, "utf8");
1382
+ op.extra_args = [
1383
+ ...(Array.isArray(op.extra_args) ? op.extra_args : []),
1384
+ "--append-system-prompt", bootstrapFile,
1385
+ ];
1386
+ } else if (normalizedAgent === "codex") {
1387
+ // codex: bootstrap via initial prompt argument
1388
+ op.extra_args = [
1389
+ ...(Array.isArray(op.extra_args) ? op.extra_args : []),
1390
+ built.promptText,
1391
+ ];
1392
+ }
1371
1393
  soloLaunchBootstrap = {
1372
1394
  requested_profile: profileResult.requested_profile,
1373
1395
  resolved_profile: profileResult.profile.id,
@@ -1377,7 +1399,7 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
1377
1399
  socket.write(
1378
1400
  `${JSON.stringify({
1379
1401
  type: IPC_RESPONSE_TYPES.ERROR,
1380
- error: err.message || "failed to prepare ucode bootstrap",
1402
+ error: err.message || "failed to prepare solo bootstrap",
1381
1403
  })}
1382
1404
  `,
1383
1405
  );