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.
- package/README.md +247 -23
- package/SKILLS/ufoo/SKILL.md +17 -2
- package/SKILLS/uinit/SKILL.md +8 -3
- package/bin/ucode-core.js +15 -0
- package/bin/ucode.js +125 -0
- package/bin/ufoo-assistant-agent.js +5 -0
- package/bin/ufoo-engine.js +25 -0
- package/bin/ufoo.js +4 -0
- package/modules/AGENTS.template.md +14 -4
- package/modules/bus/README.md +8 -5
- package/modules/bus/SKILLS/ubus/SKILL.md +5 -4
- package/modules/context/SKILLS/uctx/SKILL.md +3 -1
- package/modules/online/SKILLS/ufoo-online/SKILL.md +144 -0
- package/package.json +12 -3
- package/scripts/import-pi-mono.js +124 -0
- package/scripts/postinstall.js +20 -49
- package/scripts/sync-claude-skills.sh +21 -0
- package/src/agent/cliRunner.js +524 -31
- package/src/agent/internalRunner.js +76 -9
- package/src/agent/launcher.js +97 -45
- package/src/agent/normalizeOutput.js +1 -1
- package/src/agent/notifier.js +144 -4
- package/src/agent/ptyRunner.js +480 -10
- package/src/agent/ptyWrapper.js +28 -3
- package/src/agent/readyDetector.js +16 -0
- package/src/agent/ucode.js +443 -0
- package/src/agent/ucodeBootstrap.js +113 -0
- package/src/agent/ucodeBuild.js +67 -0
- package/src/agent/ucodeDoctor.js +184 -0
- package/src/agent/ucodeRuntimeConfig.js +129 -0
- package/src/agent/ufooAgent.js +168 -28
- package/src/assistant/agent.js +260 -0
- package/src/assistant/bridge.js +172 -0
- package/src/assistant/engine.js +252 -0
- package/src/assistant/stdio.js +58 -0
- package/src/assistant/ufooEngineCli.js +306 -0
- package/src/bus/activate.js +27 -11
- package/src/bus/daemon.js +133 -5
- package/src/bus/index.js +137 -80
- package/src/bus/inject.js +47 -17
- package/src/bus/message.js +145 -17
- package/src/bus/nickname.js +3 -1
- package/src/bus/queue.js +6 -1
- package/src/bus/store.js +189 -0
- package/src/bus/subscriber.js +20 -4
- package/src/bus/utils.js +9 -3
- package/src/chat/agentBar.js +117 -0
- package/src/chat/agentDirectory.js +88 -0
- package/src/chat/agentSockets.js +225 -0
- package/src/chat/agentViewController.js +298 -0
- package/src/chat/chatLogController.js +115 -0
- package/src/chat/commandExecutor.js +700 -0
- package/src/chat/commands.js +132 -0
- package/src/chat/completionController.js +414 -0
- package/src/chat/cronScheduler.js +160 -0
- package/src/chat/daemonConnection.js +166 -0
- package/src/chat/daemonCoordinator.js +64 -0
- package/src/chat/daemonMessageRouter.js +257 -0
- package/src/chat/daemonReconnect.js +41 -0
- package/src/chat/daemonTransport.js +36 -0
- package/src/chat/daemonTransportDefaults.js +10 -0
- package/src/chat/dashboardKeyController.js +480 -0
- package/src/chat/dashboardView.js +157 -0
- package/src/chat/index.js +938 -2910
- package/src/chat/inputHistoryController.js +105 -0
- package/src/chat/inputListenerController.js +304 -0
- package/src/chat/inputMath.js +104 -0
- package/src/chat/inputSubmitHandler.js +171 -0
- package/src/chat/layout.js +165 -0
- package/src/chat/pasteController.js +81 -0
- package/src/chat/rawKeyMap.js +42 -0
- package/src/chat/settingsController.js +133 -0
- package/src/chat/statusLineController.js +177 -0
- package/src/chat/streamTracker.js +138 -0
- package/src/chat/text.js +70 -0
- package/src/chat/transport.js +61 -0
- package/src/cli/busCoreCommands.js +59 -0
- package/src/cli/ctxCoreCommands.js +199 -0
- package/src/cli/onlineCoreCommands.js +379 -0
- package/src/cli.js +741 -238
- package/src/code/README.md +29 -0
- package/src/code/UCODE_PROMPT.md +32 -0
- package/src/code/agent.js +1651 -0
- package/src/code/cli.js +158 -0
- package/src/code/config +0 -0
- package/src/code/dispatch.js +42 -0
- package/src/code/index.js +70 -0
- package/src/code/nativeRunner.js +1213 -0
- package/src/code/runtime.js +154 -0
- package/src/code/sessionStore.js +162 -0
- package/src/code/taskDecomposer.js +269 -0
- package/src/code/tools/bash.js +53 -0
- package/src/code/tools/common.js +42 -0
- package/src/code/tools/edit.js +70 -0
- package/src/code/tools/read.js +44 -0
- package/src/code/tools/write.js +35 -0
- package/src/code/tui.js +1587 -0
- package/src/config.js +50 -2
- package/src/context/decisions.js +12 -2
- package/src/context/index.js +18 -1
- package/src/context/sync.js +127 -0
- package/src/daemon/agentProcessManager.js +74 -0
- package/src/daemon/cronOps.js +241 -0
- package/src/daemon/index.js +662 -489
- package/src/daemon/ipcServer.js +99 -0
- package/src/daemon/ops.js +417 -179
- package/src/daemon/promptLoop.js +319 -0
- package/src/daemon/promptRequest.js +101 -0
- package/src/daemon/providerSessions.js +32 -17
- package/src/daemon/reporting.js +90 -0
- package/src/daemon/run.js +2 -5
- package/src/daemon/status.js +24 -1
- package/src/init/index.js +68 -14
- package/src/online/bridge.js +663 -0
- package/src/online/client.js +245 -0
- package/src/online/runner.js +253 -0
- package/src/online/server.js +992 -0
- package/src/online/tokens.js +103 -0
- package/src/report/store.js +331 -0
- package/src/shared/eventContract.js +35 -0
- package/src/shared/ptySocketContract.js +21 -0
- package/src/status/index.js +50 -17
- package/src/terminal/adapterContract.js +87 -0
- package/src/terminal/adapterRouter.js +84 -0
- package/src/terminal/adapters/externalAdapter.js +14 -0
- package/src/terminal/adapters/internalAdapter.js +13 -0
- package/src/terminal/adapters/internalPtyAdapter.js +42 -0
- package/src/terminal/adapters/internalQueueAdapter.js +37 -0
- package/src/terminal/adapters/terminalAdapter.js +31 -0
- package/src/terminal/adapters/tmuxAdapter.js +30 -0
- package/src/ufoo/agentsStore.js +69 -3
- package/src/utils/banner.js +5 -2
- package/scripts/.archived/bash-to-js-migration/README.md +0 -46
- package/scripts/.archived/bash-to-js-migration/banner.sh +0 -89
- package/scripts/.archived/bash-to-js-migration/bus-alert.sh +0 -6
- package/scripts/.archived/bash-to-js-migration/bus-autotrigger.sh +0 -6
- package/scripts/.archived/bash-to-js-migration/bus-daemon.sh +0 -231
- package/scripts/.archived/bash-to-js-migration/bus-inject.sh +0 -176
- package/scripts/.archived/bash-to-js-migration/bus-listen.sh +0 -6
- package/scripts/.archived/bash-to-js-migration/bus.sh +0 -986
- package/scripts/.archived/bash-to-js-migration/context-decisions.sh +0 -167
- package/scripts/.archived/bash-to-js-migration/context-doctor.sh +0 -72
- package/scripts/.archived/bash-to-js-migration/context-lint.sh +0 -110
- package/scripts/.archived/bash-to-js-migration/doctor.sh +0 -22
- package/scripts/.archived/bash-to-js-migration/init.sh +0 -247
- package/scripts/.archived/bash-to-js-migration/skills.sh +0 -113
- package/scripts/.archived/bash-to-js-migration/status.sh +0 -125
- package/scripts/banner.sh +0 -2
- 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
|
|
3
|
+
🤖 Multi-agent AI collaboration framework for orchestrating Claude Code, OpenAI Codex, and custom AI agents.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/u-foo)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://nodejs.org)
|
|
8
|
+
[](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`)
|
|
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
|
-
##
|
|
35
|
+
## Installation
|
|
15
36
|
|
|
16
37
|
```bash
|
|
17
|
-
#
|
|
18
|
-
|
|
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
|
-
#
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
|
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
|
|
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
|
-
│
|
|
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
|
-
│
|
|
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
|
|
142
|
-
- Node.js >= 18
|
|
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
|
-
#
|
|
160
|
-
|
|
343
|
+
# Clone the repository
|
|
344
|
+
git clone https://github.com/Icyoung/ufoo.git
|
|
345
|
+
cd ufoo
|
|
161
346
|
|
|
162
|
-
#
|
|
347
|
+
# Install dependencies
|
|
348
|
+
npm install
|
|
349
|
+
|
|
350
|
+
# Link for local development
|
|
163
351
|
npm link
|
|
164
|
-
|
|
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:
|
package/SKILLS/ufoo/SKILL.md
CHANGED
|
@@ -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>` (
|
|
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`
|
package/SKILLS/uinit/SKILL.md
CHANGED
|
@@ -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
|
|
50
|
-
|
|
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,
|
|
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,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
|
|
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.
|
|
71
|
-
2
|
|
72
|
-
|
|
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
|
package/modules/bus/README.md
CHANGED
|
@@ -40,8 +40,9 @@ ufoo init --modules context,bus
|
|
|
40
40
|
### Join Bus
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
SUBSCRIBER
|
|
44
|
-
|
|
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
|
|
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)
|
|
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
|
|
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):
|