u-foo 1.0.0 → 1.0.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/README.md CHANGED
@@ -139,12 +139,13 @@ Built-in skills triggered by slash commands:
139
139
 
140
140
  ## Codex CLI Notes
141
141
 
142
- If Codex CLI fails with permission errors under `~/.codex` (e.g. sessions dir), set `CODEX_HOME` to a writable path before starting the daemon/chat:
142
+ `ufoo chat` automatically starts the daemon if not running - no need to run `ufoo daemon start` separately.
143
+
144
+ If Codex CLI fails with permission errors under `~/.codex` (e.g. sessions dir), set `CODEX_HOME` to a writable path:
143
145
 
144
146
  ```bash
145
147
  export CODEX_HOME="$PWD/.ufoo/codex"
146
- ufoo daemon start
147
- ufoo chat
148
+ ufoo chat # daemon auto-starts
148
149
  ```
149
150
 
150
151
  ## Development
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "u-foo",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
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",
package/src/chat/index.js CHANGED
@@ -14,6 +14,8 @@ function connectSocket(sockPath) {
14
14
  }
15
15
 
16
16
  function startDaemon(projectRoot) {
17
+ // eslint-disable-next-line no-console
18
+ console.log("Starting ufoo daemon...");
17
19
  const child = spawn(process.execPath, [path.join(projectRoot, "bin", "ufoo.js"), "daemon", "--start"], {
18
20
  detached: true,
19
21
  stdio: "ignore",
@@ -22,6 +24,20 @@ function startDaemon(projectRoot) {
22
24
  child.unref();
23
25
  }
24
26
 
27
+ async function connectWithRetry(sockPath, retries, delayMs) {
28
+ for (let i = 0; i < retries; i += 1) {
29
+ try {
30
+ // eslint-disable-next-line no-await-in-loop
31
+ const client = await connectSocket(sockPath);
32
+ return client;
33
+ } catch {
34
+ // eslint-disable-next-line no-await-in-loop
35
+ await new Promise((r) => setTimeout(r, delayMs));
36
+ }
37
+ }
38
+ return null;
39
+ }
40
+
25
41
  async function runChat(projectRoot) {
26
42
  if (!fs.existsSync(path.join(projectRoot, ".ufoo"))) {
27
43
  spawnSync("bash", [path.join(projectRoot, "scripts", "init.sh"), "--modules", "context,bus", "--project", projectRoot], {
@@ -33,16 +49,24 @@ async function runChat(projectRoot) {
33
49
  }
34
50
 
35
51
  const sock = socketPath(projectRoot);
36
- let client = null;
37
- for (let i = 0; i < 10; i += 1) {
38
- try {
39
- client = await connectSocket(sock);
40
- break;
41
- } catch {
42
- await new Promise((r) => setTimeout(r, 200));
52
+ let client = await connectWithRetry(sock, 25, 200);
53
+ if (!client) {
54
+ // Retry once with a fresh daemon start and longer wait.
55
+ if (!isRunning(projectRoot)) {
56
+ startDaemon(projectRoot);
43
57
  }
58
+ client = await connectWithRetry(sock, 50, 200);
59
+ }
60
+ if (!client) {
61
+ // Check if daemon failed to start
62
+ if (!isRunning(projectRoot)) {
63
+ const logFile = path.join(projectRoot, ".ufoo", "run", "ufoo-daemon.log");
64
+ // eslint-disable-next-line no-console
65
+ console.error("Failed to start ufoo daemon. Check logs at:", logFile);
66
+ throw new Error("Daemon failed to start. Check the daemon log for details.");
67
+ }
68
+ throw new Error("Failed to connect to ufoo daemon (timeout). The daemon may still be starting.");
44
69
  }
45
- if (!client) throw new Error("Failed to connect to ufoo daemon");
46
70
 
47
71
  const screen = blessed.screen({
48
72
  smartCSR: true,