u-foo 1.0.6 → 1.2.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 (149) hide show
  1. package/README.md +247 -23
  2. package/SKILLS/ufoo/SKILL.md +17 -2
  3. package/SKILLS/uinit/SKILL.md +8 -3
  4. package/bin/ucode-core.js +15 -0
  5. package/bin/ucode.js +125 -0
  6. package/bin/ufoo-assistant-agent.js +5 -0
  7. package/bin/ufoo-engine.js +25 -0
  8. package/bin/ufoo.js +4 -0
  9. package/modules/AGENTS.template.md +14 -4
  10. package/modules/bus/README.md +8 -5
  11. package/modules/bus/SKILLS/ubus/SKILL.md +5 -4
  12. package/modules/context/SKILLS/uctx/SKILL.md +3 -1
  13. package/modules/online/SKILLS/ufoo-online/SKILL.md +144 -0
  14. package/package.json +12 -3
  15. package/scripts/import-pi-mono.js +124 -0
  16. package/scripts/postinstall.js +20 -49
  17. package/scripts/sync-claude-skills.sh +21 -0
  18. package/src/agent/cliRunner.js +524 -31
  19. package/src/agent/internalRunner.js +76 -9
  20. package/src/agent/launcher.js +97 -45
  21. package/src/agent/normalizeOutput.js +1 -1
  22. package/src/agent/notifier.js +144 -4
  23. package/src/agent/ptyRunner.js +480 -10
  24. package/src/agent/ptyWrapper.js +28 -3
  25. package/src/agent/readyDetector.js +16 -0
  26. package/src/agent/ucode.js +443 -0
  27. package/src/agent/ucodeBootstrap.js +113 -0
  28. package/src/agent/ucodeBuild.js +67 -0
  29. package/src/agent/ucodeDoctor.js +184 -0
  30. package/src/agent/ucodeRuntimeConfig.js +129 -0
  31. package/src/agent/ufooAgent.js +168 -28
  32. package/src/assistant/agent.js +260 -0
  33. package/src/assistant/bridge.js +172 -0
  34. package/src/assistant/engine.js +252 -0
  35. package/src/assistant/stdio.js +58 -0
  36. package/src/assistant/ufooEngineCli.js +306 -0
  37. package/src/bus/activate.js +27 -11
  38. package/src/bus/daemon.js +133 -5
  39. package/src/bus/index.js +137 -80
  40. package/src/bus/inject.js +47 -17
  41. package/src/bus/message.js +145 -17
  42. package/src/bus/nickname.js +3 -1
  43. package/src/bus/queue.js +6 -1
  44. package/src/bus/store.js +189 -0
  45. package/src/bus/subscriber.js +20 -4
  46. package/src/bus/utils.js +9 -3
  47. package/src/chat/agentBar.js +117 -0
  48. package/src/chat/agentDirectory.js +88 -0
  49. package/src/chat/agentSockets.js +225 -0
  50. package/src/chat/agentViewController.js +298 -0
  51. package/src/chat/chatLogController.js +115 -0
  52. package/src/chat/commandExecutor.js +700 -0
  53. package/src/chat/commands.js +132 -0
  54. package/src/chat/completionController.js +414 -0
  55. package/src/chat/cronScheduler.js +160 -0
  56. package/src/chat/daemonConnection.js +166 -0
  57. package/src/chat/daemonCoordinator.js +64 -0
  58. package/src/chat/daemonMessageRouter.js +257 -0
  59. package/src/chat/daemonReconnect.js +41 -0
  60. package/src/chat/daemonTransport.js +36 -0
  61. package/src/chat/daemonTransportDefaults.js +10 -0
  62. package/src/chat/dashboardKeyController.js +480 -0
  63. package/src/chat/dashboardView.js +157 -0
  64. package/src/chat/index.js +938 -2910
  65. package/src/chat/inputHistoryController.js +105 -0
  66. package/src/chat/inputListenerController.js +304 -0
  67. package/src/chat/inputMath.js +104 -0
  68. package/src/chat/inputSubmitHandler.js +171 -0
  69. package/src/chat/layout.js +165 -0
  70. package/src/chat/pasteController.js +81 -0
  71. package/src/chat/rawKeyMap.js +42 -0
  72. package/src/chat/settingsController.js +133 -0
  73. package/src/chat/statusLineController.js +177 -0
  74. package/src/chat/streamTracker.js +138 -0
  75. package/src/chat/text.js +70 -0
  76. package/src/chat/transport.js +61 -0
  77. package/src/cli/busCoreCommands.js +59 -0
  78. package/src/cli/ctxCoreCommands.js +199 -0
  79. package/src/cli/onlineCoreCommands.js +379 -0
  80. package/src/cli.js +741 -238
  81. package/src/code/README.md +29 -0
  82. package/src/code/UCODE_PROMPT.md +32 -0
  83. package/src/code/agent.js +1651 -0
  84. package/src/code/cli.js +158 -0
  85. package/src/code/config +0 -0
  86. package/src/code/dispatch.js +42 -0
  87. package/src/code/index.js +70 -0
  88. package/src/code/nativeRunner.js +1213 -0
  89. package/src/code/runtime.js +154 -0
  90. package/src/code/sessionStore.js +162 -0
  91. package/src/code/taskDecomposer.js +269 -0
  92. package/src/code/tools/bash.js +53 -0
  93. package/src/code/tools/common.js +42 -0
  94. package/src/code/tools/edit.js +70 -0
  95. package/src/code/tools/read.js +44 -0
  96. package/src/code/tools/write.js +35 -0
  97. package/src/code/tui.js +1587 -0
  98. package/src/config.js +50 -2
  99. package/src/context/decisions.js +12 -2
  100. package/src/context/index.js +18 -1
  101. package/src/context/sync.js +127 -0
  102. package/src/daemon/agentProcessManager.js +74 -0
  103. package/src/daemon/cronOps.js +241 -0
  104. package/src/daemon/index.js +662 -489
  105. package/src/daemon/ipcServer.js +99 -0
  106. package/src/daemon/ops.js +417 -179
  107. package/src/daemon/promptLoop.js +319 -0
  108. package/src/daemon/promptRequest.js +101 -0
  109. package/src/daemon/providerSessions.js +32 -17
  110. package/src/daemon/reporting.js +90 -0
  111. package/src/daemon/run.js +2 -5
  112. package/src/daemon/status.js +24 -1
  113. package/src/init/index.js +68 -14
  114. package/src/online/bridge.js +663 -0
  115. package/src/online/client.js +245 -0
  116. package/src/online/runner.js +253 -0
  117. package/src/online/server.js +992 -0
  118. package/src/online/tokens.js +103 -0
  119. package/src/report/store.js +331 -0
  120. package/src/shared/eventContract.js +35 -0
  121. package/src/shared/ptySocketContract.js +21 -0
  122. package/src/status/index.js +50 -17
  123. package/src/terminal/adapterContract.js +87 -0
  124. package/src/terminal/adapterRouter.js +84 -0
  125. package/src/terminal/adapters/externalAdapter.js +14 -0
  126. package/src/terminal/adapters/internalAdapter.js +13 -0
  127. package/src/terminal/adapters/internalPtyAdapter.js +42 -0
  128. package/src/terminal/adapters/internalQueueAdapter.js +37 -0
  129. package/src/terminal/adapters/terminalAdapter.js +31 -0
  130. package/src/terminal/adapters/tmuxAdapter.js +30 -0
  131. package/src/ufoo/agentsStore.js +69 -3
  132. package/src/utils/banner.js +5 -2
  133. package/scripts/.archived/bash-to-js-migration/README.md +0 -46
  134. package/scripts/.archived/bash-to-js-migration/banner.sh +0 -89
  135. package/scripts/.archived/bash-to-js-migration/bus-alert.sh +0 -6
  136. package/scripts/.archived/bash-to-js-migration/bus-autotrigger.sh +0 -6
  137. package/scripts/.archived/bash-to-js-migration/bus-daemon.sh +0 -231
  138. package/scripts/.archived/bash-to-js-migration/bus-inject.sh +0 -176
  139. package/scripts/.archived/bash-to-js-migration/bus-listen.sh +0 -6
  140. package/scripts/.archived/bash-to-js-migration/bus.sh +0 -986
  141. package/scripts/.archived/bash-to-js-migration/context-decisions.sh +0 -167
  142. package/scripts/.archived/bash-to-js-migration/context-doctor.sh +0 -72
  143. package/scripts/.archived/bash-to-js-migration/context-lint.sh +0 -110
  144. package/scripts/.archived/bash-to-js-migration/doctor.sh +0 -22
  145. package/scripts/.archived/bash-to-js-migration/init.sh +0 -247
  146. package/scripts/.archived/bash-to-js-migration/skills.sh +0 -113
  147. package/scripts/.archived/bash-to-js-migration/status.sh +0 -125
  148. package/scripts/banner.sh +0 -2
  149. package/src/bus/API_DESIGN.md +0 -204
package/README.md CHANGED
@@ -1,32 +1,159 @@
1
1
  # ufoo
2
2
 
3
- Multi-agent AI collaboration toolkit for Claude Code and OpenAI Codex.
3
+ 🤖 Multi-agent AI collaboration framework for orchestrating Claude Code, OpenAI Codex, and custom AI agents.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/u-foo.svg)](https://www.npmjs.com/package/u-foo)
6
+ [![License](https://img.shields.io/badge/license-UNLICENSED-red.svg)](LICENSE)
7
+ [![Node](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org)
8
+ [![Platform](https://img.shields.io/badge/platform-macOS-blue.svg)](https://www.apple.com/macos)
9
+
10
+ ## Why ufoo?
11
+
12
+ ufoo solves the challenge of coordinating multiple AI coding agents:
13
+
14
+ - **🔗 Unified Interface** - One chat UI to manage all your AI agents
15
+ - **📬 Message Routing** - Agents can communicate and collaborate via event bus
16
+ - **🧠 Context Sharing** - Shared decisions and knowledge across agents
17
+ - **🚀 Auto-initialization** - Agent wrappers handle setup automatically
18
+ - **📝 Decision Tracking** - Record architectural decisions and trade-offs
19
+ - **⚡ Real-time Updates** - See agent status and messages instantly
4
20
 
5
21
  ## Features
6
22
 
23
+ - **Chat Interface** - Interactive multi-agent chat UI (`ufoo chat`)
24
+ - Real-time agent communication and status monitoring
25
+ - Dashboard with agent list, online status, and quick actions
26
+ - Direct messaging to specific agents with `@agent-name`
7
27
  - **Event Bus** - Real-time inter-agent messaging (`ufoo bus`)
8
28
  - **Context Sharing** - Shared decisions and project context (`ufoo ctx`)
9
- - **Agent Wrappers** - Auto-initialization for Claude Code (`uclaude`) and Codex (`ucodex`)
29
+ - **Agent Wrappers** - Auto-initialization for Claude Code (`uclaude`), Codex (`ucodex`), and ucode assistant (`ucode`)
10
30
  - **PTY Wrapper** - Intelligent terminal emulation with ready detection
11
31
  - **Smart Probe Injection** - Waits for agent initialization before injecting commands
32
+ - **Consistent Branding** - Unified agent naming (e.g., ucode-1, claude-1, codex-1)
12
33
  - **Skills System** - Extensible agent capabilities (`ufoo skills`)
13
34
 
14
- ## Quick Start
35
+ ## Installation
15
36
 
16
37
  ```bash
17
- # Clone and link globally
18
- git clone <repo> ~/.ufoo
38
+ # Install globally from npm
39
+ npm install -g u-foo
40
+
41
+ # Or clone from source
42
+ git clone https://github.com/Icyoung/ufoo.git ~/.ufoo
19
43
  cd ~/.ufoo && npm link
44
+ ```
20
45
 
46
+ ## Quick Start
47
+
48
+ ```bash
21
49
  # Initialize a project
22
50
  cd your-project
23
51
  ufoo init
24
52
 
25
- # Or use agent wrappers (auto-init + bus join)
26
- uclaude # instead of 'claude'
27
- ucodex # instead of 'codex'
53
+ # Launch chat interface (default command)
54
+ ufoo chat
55
+ # or just
56
+ ufoo
57
+
58
+ # Use agent wrappers (auto-init + bus join)
59
+ uclaude # Claude Code wrapper
60
+ ucodex # Codex wrapper
61
+ ucode # ucode assistant (self-developed AI coding agent)
62
+ ```
63
+
64
+ ## Example Workflow
65
+
66
+ ```bash
67
+ # 1. Start the chat interface
68
+ $ ufoo
69
+
70
+ # 2. Launch agents from chat
71
+ > /launch claude
72
+ > /launch ucode
73
+
74
+ # 3. Send tasks to agents
75
+ > @claude-1 Please analyze the current codebase structure
76
+ > @ucode-1 Fix the bug in authentication module
77
+
78
+ # 4. Agents communicate via bus
79
+ claude-1: Analysis complete. Found 3 areas needing refactoring...
80
+ ucode-1: Bug fixed. Running tests...
81
+
82
+ # 5. Check decisions made
83
+ > /decisions
28
84
  ```
29
85
 
86
+ To import a local `pi-mono` checkout as a reference snapshot (reference-only):
87
+
88
+ ```bash
89
+ npm run import:pi-mono -- /path/to/pi-mono
90
+ ```
91
+
92
+ Native self-developed implementation lives under `src/code`.
93
+
94
+ Prepare and verify `ucode` runtime wiring:
95
+
96
+ ```bash
97
+ ufoo ucode doctor
98
+ ufoo ucode prepare
99
+ ufoo ucode build
100
+ ```
101
+
102
+ Try native core queue runtime (WIP):
103
+
104
+ ```bash
105
+ ucode-core submit --tool read --args-json '{"path":"README.md"}'
106
+ ucode-core run-once --json
107
+ ucode-core list --json
108
+ ```
109
+
110
+ ## Agent Configuration
111
+
112
+ Configure AI providers in `.ufoo/config.json`:
113
+
114
+ ### ucode Configuration (Self-developed Assistant)
115
+ ```json
116
+ {
117
+ "ucodeProvider": "openai", // or "anthropic", "azure", etc.
118
+ "ucodeModel": "gpt-4-turbo-preview",
119
+ "ucodeBaseUrl": "https://api.openai.com/v1",
120
+ "ucodeApiKey": "sk-***"
121
+ }
122
+ ```
123
+
124
+ ### Claude Configuration
125
+ ```json
126
+ {
127
+ "claudeProvider": "claude-cli", // Uses Claude CLI
128
+ "claudeModel": "claude-3-opus" // or "claude-3-sonnet"
129
+ }
130
+ ```
131
+
132
+ ### Codex Configuration
133
+ ```json
134
+ {
135
+ "codexProvider": "codex-cli", // Uses Codex CLI
136
+ "codexModel": "gpt-4" // or "gpt-4-turbo-preview"
137
+ }
138
+ ```
139
+
140
+ ### Complete Example
141
+ ```json
142
+ {
143
+ "launchMode": "internal",
144
+ "ucodeProvider": "openai",
145
+ "ucodeModel": "gpt-4-turbo-preview",
146
+ "ucodeBaseUrl": "https://api.openai.com/v1",
147
+ "ucodeApiKey": "sk-***",
148
+ "claudeProvider": "claude-cli",
149
+ "claudeModel": "claude-3-opus",
150
+ "codexProvider": "codex-cli",
151
+ "codexModel": "gpt-4"
152
+ }
153
+ ```
154
+
155
+ `ucode` writes these into a dedicated runtime directory (`.ufoo/agent/ucode/pi-agent`) and uses them for native planner/engine calls.
156
+
30
157
  ## Architecture
31
158
 
32
159
  ```
@@ -51,21 +178,43 @@ Bus state lives in `.ufoo/agent/all-agents.json` (metadata), `.ufoo/bus/*` (queu
51
178
 
52
179
  ## Commands
53
180
 
181
+ ### Core Commands
54
182
  | Command | Description |
55
183
  |---------|-------------|
184
+ | `ufoo` | Launch chat interface (default) |
185
+ | `ufoo chat` | Launch interactive multi-agent chat UI |
56
186
  | `ufoo init` | Initialize .ufoo in current project |
57
187
  | `ufoo status` | Show banner, unread bus messages, open decisions |
58
- | `ufoo daemon --start|--stop|--status` | Manage ufoo daemon |
59
- | `ufoo chat` | Launch ufoo chat UI (also default when no args) |
60
- | `ufoo resume [nickname]` | Resume agent sessions (optional nickname) |
61
- | `ufoo bus join` | Join event bus (auto by uclaude/ucodex) |
188
+ | `ufoo doctor` | Check installation health |
189
+
190
+ ### Agent Management
191
+ | Command | Description |
192
+ |---------|-------------|
193
+ | `ufoo daemon start` | Start ufoo daemon |
194
+ | `ufoo daemon stop` | Stop ufoo daemon |
195
+ | `ufoo daemon status` | Check daemon status |
196
+ | `ufoo resume [nickname]` | Resume agent sessions |
197
+
198
+ ### Event Bus
199
+ | Command | Description |
200
+ |---------|-------------|
201
+ | `ufoo bus join` | Join event bus (auto by agent wrappers) |
62
202
  | `ufoo bus send <id> <msg>` | Send message to agent |
63
203
  | `ufoo bus check <id>` | Check pending messages |
64
- | `ufoo bus status` | Show bus status |
204
+ | `ufoo bus status` | Show bus status and online agents |
205
+
206
+ ### Context & Decisions
207
+ | Command | Description |
208
+ |---------|-------------|
65
209
  | `ufoo ctx decisions -l` | List all decisions |
66
210
  | `ufoo ctx decisions -n 1` | Show latest decision |
211
+ | `ufoo ctx decisions new <title>` | Create new decision |
212
+
213
+ ### Skills
214
+ | Command | Description |
215
+ |---------|-------------|
67
216
  | `ufoo skills list` | List available skills |
68
- | `ufoo doctor` | Check installation health |
217
+ | `ufoo skills show <skill>` | Show skill details |
69
218
 
70
219
  Notes:
71
220
  - Claude CLI headless agent uses `--dangerously-skip-permissions`.
@@ -78,12 +227,14 @@ ufoo/
78
227
  │ ├── ufoo # Main CLI entry (bash)
79
228
  │ ├── ufoo.js # Node wrapper
80
229
  │ ├── uclaude # Claude Code wrapper
81
- └── ucodex # Codex wrapper
230
+ ├── ucodex # Codex wrapper
231
+ │ └── ucode # ucode assistant wrapper
82
232
  ├── SKILLS/ # Global skills (uinit, ustatus)
83
233
  ├── src/
84
234
  │ ├── bus/ # Event bus implementation (JS)
85
235
  │ ├── daemon/ # Daemon + chat bridge
86
- └── agent/ # Agent launch/runtime
236
+ ├── agent/ # Agent launch/runtime
237
+ │ └── code/ # Native ucode core implementation
87
238
  ├── scripts/ # Legacy helpers (bash, deprecated)
88
239
  ├── modules/
89
240
  │ ├── context/ # Decision/context protocol
@@ -112,6 +263,37 @@ your-project/
112
263
  └── CLAUDE.md # → AGENTS.md
113
264
  ```
114
265
 
266
+ ## Chat Interface
267
+
268
+ The interactive chat UI provides a centralized hub for agent management:
269
+
270
+ ### Features
271
+ - **Real-time Communication** - See all agent messages in one place
272
+ - **Agent Dashboard** - Monitor online status, session IDs, and nicknames
273
+ - **Direct Messaging** - Use `@agent-name` to target specific agents
274
+ - **Command Completion** - Tab completion for commands and agent names
275
+ - **Mouse Support** - Toggle with `Ctrl+M` for scrolling vs text selection
276
+ - **Session History** - Persistent message history across sessions
277
+
278
+ ### Keyboard Shortcuts
279
+ | Key | Action |
280
+ |-----|--------|
281
+ | `Tab` | Auto-complete commands/agents |
282
+ | `Ctrl+C` | Exit chat |
283
+ | `Ctrl+M` | Toggle mouse mode |
284
+ | `Ctrl+L` | Clear screen |
285
+ | `Ctrl+R` | Refresh agent list |
286
+ | `↑/↓` | Navigate command history |
287
+
288
+ ### Chat Commands
289
+ | Command | Description |
290
+ |---------|-------------|
291
+ | `/help` | Show available commands |
292
+ | `/agents` | List online agents |
293
+ | `/clear` | Clear chat history |
294
+ | `/settings` | Configure chat preferences |
295
+ | `@agent-name <message>` | Send to specific agent |
296
+
115
297
  ## Agent Communication
116
298
 
117
299
  Agents communicate via the event bus:
@@ -138,9 +320,10 @@ Built-in skills triggered by slash commands:
138
320
 
139
321
  ## Requirements
140
322
 
141
- - macOS (for Terminal.app/iTerm2 injection features)
142
- - Node.js >= 18 (optional, for npm global install)
143
- - Bash 4+
323
+ - **macOS** - Required for Terminal.app/iTerm2 integration
324
+ - **Node.js >= 18** - For npm installation and JavaScript runtime
325
+ - **Bash 4+** - For shell scripts and command execution
326
+ - **Terminal** - iTerm2 or Terminal.app for agent launching
144
327
 
145
328
  ## Codex CLI Notes
146
329
 
@@ -155,21 +338,62 @@ ufoo chat # daemon auto-starts
155
338
 
156
339
  ## Development
157
340
 
341
+ ### Setup
158
342
  ```bash
159
- # Local development
160
- ./bin/ufoo --help
343
+ # Clone the repository
344
+ git clone https://github.com/Icyoung/ufoo.git
345
+ cd ufoo
161
346
 
162
- # Or via Node
347
+ # Install dependencies
348
+ npm install
349
+
350
+ # Link for local development
163
351
  npm link
164
- ufoo --help
352
+
353
+ # Run tests
354
+ npm test
165
355
  ```
166
356
 
357
+ ### Contributing
358
+ - Fork the repository
359
+ - Create a feature branch (`git checkout -b feature/amazing-feature`)
360
+ - Commit your changes (`git commit -m 'Add amazing feature'`)
361
+ - Push to the branch (`git push origin feature/amazing-feature`)
362
+ - Open a Pull Request
363
+
364
+ ### Project Structure
365
+ - `src/` - Core JavaScript implementation
366
+ - `bin/` - CLI entry points
367
+ - `modules/` - Modular features (bus, context, etc.)
368
+ - `test/` - Unit and integration tests
369
+ - `SKILLS/` - Agent skill definitions
370
+
167
371
  ## License
168
372
 
169
373
  UNLICENSED (Private)
170
374
 
171
375
  ## Recent Changes
172
376
 
377
+ ### 🎨 UCode Branding & UI Improvements (2026-02-15)
378
+
379
+ Enhanced ucode agent branding consistency and fixed UI rendering issues:
380
+
381
+ **Features:**
382
+ - **Consistent Branding** - ucode agents now display as "ucode-1" instead of "ufoo-code-1"
383
+ - **Banner Normalization** - Agent type shows "ucode" in launch banners
384
+ - **UI Width Fix** - Resolved terminal width inconsistency causing background overflow
385
+ - **Immediate Prompt Display** - ucode TUI now shows incoming prompts instantly (not waiting for response)
386
+
387
+ **Technical Details:**
388
+ - `src/bus/nickname.js` - Maps ufoo-code → ucode for nickname generation
389
+ - `src/utils/banner.js` - Normalized agent type display
390
+ - `src/chat/layout.js` - Fixed blessed log component width handling
391
+ - `src/code/tui.js` - Added onMessageReceived callback for instant display
392
+
393
+ **Version:** v1.1.9
394
+
395
+ ---
396
+
173
397
  ### 🚀 Smart Ready Detection & PTY Wrapper (2026-02-06)
174
398
 
175
399
  Added intelligent agent initialization detection for reliable probe injection:
@@ -2,7 +2,7 @@
2
2
  name: ufoo
3
3
  description: |
4
4
  Unified ufoo agent protocol: context decisions, event bus, and initialization.
5
- Use when: (1) input starts with "/ufoo", (2) agent session startup, (3) any ufoo-related operation.
5
+ Use when: (1) input starts with "/ufoo" or "$ufoo", (2) agent session startup, (3) any ufoo-related operation.
6
6
  Combines uctx (decisions), ubus (messaging), and uinit (initialization).
7
7
  ---
8
8
 
@@ -16,7 +16,7 @@ ufoo is the multi-agent coordination layer. It provides three capabilities:
16
16
 
17
17
  ## Session Marker
18
18
 
19
- When you see `/ufoo <marker>` (e.g., `/ufoo claude-9`), this is a daemon probe for session tracking. **Do not reply.** Silently ignore it and wait for the next user input.
19
+ When you see a probe marker command like `/ufoo <marker>` (Claude) or `$ufoo <marker>` (Codex), this is daemon session tracking. **Do not reply.** Silently ignore it and wait for the next user input.
20
20
 
21
21
  ---
22
22
 
@@ -88,6 +88,21 @@ ufoo bus broadcast "<message>" # Broadcast to all
88
88
  ufoo bus status # Show bus status
89
89
  ```
90
90
 
91
+ ### Runtime Report (Unified for assistant/ucodex/uclaude)
92
+
93
+ Use the same report contract for runtime progress sync:
94
+
95
+ ```bash
96
+ ufoo report start "<task>" --task <id> --agent "$UFOO_SUBSCRIBER_ID" --scope public
97
+ ufoo report progress "<detail>" --task <id> --agent "$UFOO_SUBSCRIBER_ID" --scope public
98
+ ufoo report done "<summary>" --task <id> --agent "$UFOO_SUBSCRIBER_ID" --scope public
99
+ ufoo report error "<reason>" --task <id> --agent "$UFOO_SUBSCRIBER_ID" --scope public
100
+ ```
101
+
102
+ Notes:
103
+ - Use `--scope private` for helper-internal reports (assistant-like private channel).
104
+ - `--controller ufoo-agent` routes report events to the ufoo-agent private inbox.
105
+
91
106
  ### Target Resolution
92
107
 
93
108
  - Exact ID: `claude-code:abc123`
@@ -46,8 +46,13 @@ ufoo init --modules <selected_modules> --project $(pwd)
46
46
  ### 3. If bus module selected, auto-join bus
47
47
 
48
48
  ```bash
49
- SUBSCRIBER=$(ufoo bus join | tail -1)
50
- echo "Joined event bus: $SUBSCRIBER"
49
+ SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"
50
+ if [ -n "$SUBSCRIBER" ]; then
51
+ echo "Using existing subscriber ID: $SUBSCRIBER"
52
+ else
53
+ SUBSCRIBER=$(ufoo bus join | tail -1)
54
+ echo "Joined event bus: $SUBSCRIBER"
55
+ fi
51
56
  ```
52
57
 
53
58
  ### 4. Report initialization result
@@ -69,5 +74,5 @@ Next steps:
69
74
  ## Notes
70
75
 
71
76
  - If .ufoo/context, .ufoo/bus, or .ufoo/agent already exists, skip creation
72
- - After initialization, auto-join event bus (if bus enabled)
77
+ - After initialization, reuse existing subscriber ID first, join only as fallback (if bus enabled)
73
78
  - AGENTS.md will have protocol description block injected
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { runUcodeCoreCli } = require("../src/code/cli");
4
+
5
+ (async () => {
6
+ const argv = process.argv.slice(2);
7
+ const result = await runUcodeCoreCli({ argv, projectRoot: process.cwd() });
8
+ if (result && typeof result.output === "string" && result.output) {
9
+ process.stdout.write(result.output);
10
+ }
11
+ process.exit(typeof result.exitCode === "number" ? result.exitCode : 0);
12
+ })().catch((err) => {
13
+ process.stderr.write(`${err && err.message ? err.message : "ucode-core failed"}\n`);
14
+ process.exit(1);
15
+ });
package/bin/ucode.js ADDED
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ucode: Launch ufoo self-developed coding agent core
4
+ *
5
+ * Usage: ucode [core args...]
6
+ *
7
+ * Command resolution order:
8
+ * 1) UFOO_UCODE_CMD / UFOO_UFOO_CODE_CMD
9
+ * 2) .ufoo/config.json -> ucodeCommand / ufooCodeCommand
10
+ * 3) fallback: bundled native core entry
11
+ */
12
+
13
+ const fs = require("fs");
14
+ const AgentLauncher = require("../src/agent/launcher");
15
+ const { resolveUcodeLaunch } = require("../src/agent/ucode");
16
+ const { prepareUcodeBootstrap } = require("../src/agent/ucodeBootstrap");
17
+ const { prepareUcodeRuntimeConfig } = require("../src/agent/ucodeRuntimeConfig");
18
+
19
+ function stripAppendSystemPromptArgs(args = [], targetFile = "") {
20
+ const normalizedTarget = String(targetFile || "").trim();
21
+ if (!Array.isArray(args) || args.length === 0) return { args: [], removed: false };
22
+ const nextArgs = [];
23
+ let removed = false;
24
+ for (let i = 0; i < args.length; i += 1) {
25
+ const item = String(args[i] || "");
26
+ if (!item) continue;
27
+ if (item === "--append-system-prompt") {
28
+ const value = String(args[i + 1] || "");
29
+ if (!normalizedTarget || value === normalizedTarget) {
30
+ removed = true;
31
+ i += 1;
32
+ continue;
33
+ }
34
+ nextArgs.push(item, value);
35
+ i += 1;
36
+ continue;
37
+ }
38
+ if (item.startsWith("--append-system-prompt=")) {
39
+ const value = item.slice("--append-system-prompt=".length);
40
+ if (!normalizedTarget || value === normalizedTarget) {
41
+ removed = true;
42
+ continue;
43
+ }
44
+ }
45
+ nextArgs.push(item);
46
+ }
47
+ return { args: nextArgs, removed };
48
+ }
49
+
50
+ function shouldPreserveAppendTarget({
51
+ appendTarget = "",
52
+ bootstrapFile = "",
53
+ } = {}) {
54
+ const append = String(appendTarget || "").trim();
55
+ if (!append) return false;
56
+ const bootstrap = String(bootstrapFile || "").trim();
57
+ if (!bootstrap) return fs.existsSync(append);
58
+ if (append === bootstrap) return false;
59
+ return fs.existsSync(append);
60
+ }
61
+
62
+ const resolved = resolveUcodeLaunch({
63
+ argv: process.argv.slice(2),
64
+ env: process.env,
65
+ cwd: process.cwd(),
66
+ });
67
+
68
+ if (resolved && resolved.env && typeof resolved.env === "object") {
69
+ for (const [key, value] of Object.entries(resolved.env)) {
70
+ if (!key) continue;
71
+ process.env[key] = String(value);
72
+ }
73
+ }
74
+
75
+ try {
76
+ const runtimePrepared = prepareUcodeRuntimeConfig({
77
+ projectRoot: process.cwd(),
78
+ env: process.env,
79
+ });
80
+ if (runtimePrepared && runtimePrepared.env && typeof runtimePrepared.env === "object") {
81
+ for (const [key, value] of Object.entries(runtimePrepared.env)) {
82
+ if (!key) continue;
83
+ process.env[key] = String(value);
84
+ }
85
+ }
86
+ } catch {
87
+ // runtime config preparation is best-effort
88
+ }
89
+
90
+ try {
91
+ prepareUcodeBootstrap({
92
+ projectRoot: process.cwd(),
93
+ promptFile: process.env.UFOO_UCODE_PROMPT_FILE || "",
94
+ targetFile: process.env.UFOO_UCODE_BOOTSTRAP_FILE || "",
95
+ });
96
+ } catch (err) {
97
+ const mode = String(process.env.UFOO_UCODE_APPEND_SYSTEM_PROMPT_MODE || "auto").trim().toLowerCase();
98
+ const bootstrapFile = String(process.env.UFOO_UCODE_BOOTSTRAP_FILE || "").trim();
99
+ const appendTarget = String(process.env.UFOO_UCODE_APPEND_SYSTEM_PROMPT || bootstrapFile).trim();
100
+ const preserveCustomAppend = shouldPreserveAppendTarget({ appendTarget, bootstrapFile });
101
+ if (mode !== "always" && !preserveCustomAppend) {
102
+ const stripped = stripAppendSystemPromptArgs(resolved.args, appendTarget);
103
+ resolved.args = stripped.args;
104
+ if (stripped.removed) {
105
+ console.error(`[ucode] Warning: bootstrap prepare failed; launching without --append-system-prompt (${err && err.message ? err.message : "unknown error"})`);
106
+ }
107
+ } else if (preserveCustomAppend) {
108
+ console.error(`[ucode] Warning: bootstrap prepare failed; preserving custom --append-system-prompt (${err && err.message ? err.message : "unknown error"})`);
109
+ }
110
+ }
111
+
112
+ const mode = String(process.env.UFOO_UCODE_APPEND_SYSTEM_PROMPT_MODE || "auto").trim().toLowerCase();
113
+ const bootstrapFile = String(process.env.UFOO_UCODE_BOOTSTRAP_FILE || "").trim();
114
+ const appendTarget = String(process.env.UFOO_UCODE_APPEND_SYSTEM_PROMPT || bootstrapFile).trim();
115
+ const preserveCustomAppend = shouldPreserveAppendTarget({ appendTarget, bootstrapFile });
116
+ if (mode !== "always" && bootstrapFile && !fs.existsSync(bootstrapFile) && !preserveCustomAppend) {
117
+ const stripped = stripAppendSystemPromptArgs(resolved.args, appendTarget);
118
+ resolved.args = stripped.args;
119
+ if (stripped.removed) {
120
+ console.error("[ucode] Warning: bootstrap file missing; launching without --append-system-prompt");
121
+ }
122
+ }
123
+
124
+ const launcher = new AgentLauncher(resolved.agentType, resolved.command);
125
+ launcher.launch(resolved.args);
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { runAssistantStdio } = require("../src/assistant/stdio");
4
+
5
+ runAssistantStdio();
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { runUfooEngineCli } = require("../src/assistant/ufooEngineCli");
4
+
5
+ function readStdin() {
6
+ return new Promise((resolve) => {
7
+ let data = "";
8
+ process.stdin.setEncoding("utf8");
9
+ process.stdin.on("data", (chunk) => {
10
+ data += chunk;
11
+ });
12
+ process.stdin.on("end", () => resolve(data));
13
+ process.stdin.resume();
14
+ });
15
+ }
16
+
17
+ (async () => {
18
+ const stdinText = await readStdin();
19
+ const result = await runUfooEngineCli({
20
+ argv: process.argv.slice(2),
21
+ stdinText,
22
+ });
23
+ process.stdout.write(result.output);
24
+ process.exitCode = result.exitCode;
25
+ })();
package/bin/ufoo.js CHANGED
@@ -27,6 +27,10 @@ async function main() {
27
27
  try {
28
28
  await runPtyRunner({ projectRoot: process.cwd(), agentType });
29
29
  } catch (err) {
30
+ const normalized = String(agentType || "").trim().toLowerCase();
31
+ if (normalized === "ufoo" || normalized === "ucode" || normalized === "ufoo-code") {
32
+ throw err;
33
+ }
30
34
  // Fallback to headless runner if PTY is unavailable
31
35
  // eslint-disable-next-line no-console
32
36
  console.error(`[pty-runner] ${err.message || err}. Falling back to headless internal runner.`);
@@ -27,10 +27,17 @@ ufoo ctx decisions -l # List all decisions
27
27
  ufoo ctx decisions -n 1 # Show latest decision
28
28
 
29
29
  # Bus
30
- ufoo bus join # Join bus (auto by uclaude/ucodex)
30
+ SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"
31
+ [ -n "$SUBSCRIBER" ] || SUBSCRIBER=$(ufoo bus join | tail -1)
31
32
  ufoo bus check $SUBSCRIBER # Check pending messages
32
33
  ufoo bus send "<id>" "<msg>" # Send message
33
34
  ufoo bus status # Show bus status
35
+
36
+ # Runtime report (shared contract for assistant/ucodex/uclaude)
37
+ ufoo report start "<task>" --task <id> --agent "$SUBSCRIBER" --scope public
38
+ ufoo report progress "<detail>" --task <id> --agent "$SUBSCRIBER" --scope public
39
+ ufoo report done "<summary>" --task <id> --agent "$SUBSCRIBER" --scope public
40
+ ufoo report error "<reason>" --task <id> --agent "$SUBSCRIBER" --scope public
34
41
  ```
35
42
 
36
43
  ---
@@ -67,9 +74,12 @@ ufoo ctx decisions new "Short descriptive title"
67
74
  ### CRITICAL: `ubus` Command Behavior
68
75
 
69
76
  **When you receive `ubus`, you MUST:**
70
- 1. Check pending messages: `ufoo bus check $SUBSCRIBER`
71
- 2. **EXECUTE each task immediately** - Do NOT ask the user
72
- 3. Reply to sender: `ufoo bus send "<publisher>" "<result>"`
77
+ 1. Resolve subscriber ID first (reuse existing ID, join only as fallback):
78
+ `SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"; [ -n "$SUBSCRIBER" ] || SUBSCRIBER=$(ufoo bus join | tail -1)`
79
+ 2. Check pending messages: `ufoo bus check $SUBSCRIBER`
80
+ 3. **EXECUTE each task immediately** - Do NOT ask the user
81
+ 4. Reply to sender: `ufoo bus send "<publisher>" "<result>"`
82
+ 5. **CRITICAL: Acknowledge messages after handling**: `ufoo bus ack $SUBSCRIBER`
73
83
 
74
84
  **Rules:**
75
85
  - Execute tasks immediately without asking
@@ -40,8 +40,9 @@ ufoo init --modules context,bus
40
40
  ### Join Bus
41
41
 
42
42
  ```bash
43
- SUBSCRIBER=$(ufoo bus join | tail -n 1)
44
- # Output: claude-code:a1b2c3
43
+ SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"
44
+ [ -n "$SUBSCRIBER" ] || SUBSCRIBER=$(ufoo bus join | tail -n 1)
45
+ # Output: claude-code:a1b2c3 (or codex:def456)
45
46
  ```
46
47
 
47
48
  ### Check Pending Messages
@@ -74,7 +75,8 @@ ufoo bus status
74
75
  If you want to receive "new message alerts" while running Codex/Claude in another terminal, use **agent-side alert/listen** (avoids IME/accessibility permission/window positioning fragmentation issues):
75
76
 
76
77
  ```bash
77
- SUBSCRIBER=$(ufoo bus join | tail -n 1)
78
+ SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"
79
+ [ -n "$SUBSCRIBER" ] || SUBSCRIBER=$(ufoo bus join | tail -n 1)
78
80
 
79
81
  # Background alert: title badge + bell + optional macOS notification center
80
82
  ufoo bus alert "$SUBSCRIBER" 1 --notify --daemon
@@ -87,10 +89,11 @@ ufoo bus listen "$SUBSCRIBER" --from-beginning
87
89
 
88
90
  If you need **Claude A to notify Claude B / Codex C and have the target auto-execute** (e.g., auto-trigger `/ubus`), use the bus daemon:
89
91
 
90
- 1) First `join` in each terminal session (records `tty`, also records `TMUX_PANE` if in tmux):
92
+ 1) Resolve subscriber in each terminal session first (records `tty`, also records `TMUX_PANE` if in tmux). Join only as fallback:
91
93
 
92
94
  ```bash
93
- SUBSCRIBER=$(ufoo bus join | tail -n 1)
95
+ SUBSCRIBER="${UFOO_SUBSCRIBER_ID:-$(ufoo bus whoami 2>/dev/null || true)}"
96
+ [ -n "$SUBSCRIBER" ] || SUBSCRIBER=$(ufoo bus join | tail -n 1)
94
97
  ```
95
98
 
96
99
  2) Start the bus daemon in the project (runs as background daemon):