u-foo 1.0.3 → 1.1.9

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 (179) hide show
  1. package/README.md +110 -11
  2. package/README.zh-CN.md +9 -7
  3. package/SKILLS/ufoo/SKILL.md +132 -0
  4. package/SKILLS/uinit/SKILL.md +78 -0
  5. package/SKILLS/ustatus/SKILL.md +36 -0
  6. package/bin/uclaude.js +13 -0
  7. package/bin/ucode-core.js +15 -0
  8. package/bin/ucode.js +125 -0
  9. package/bin/ucodex.js +13 -0
  10. package/bin/ufoo +9 -31
  11. package/bin/ufoo-assistant-agent.js +5 -0
  12. package/bin/ufoo-engine.js +25 -0
  13. package/bin/ufoo.js +17 -0
  14. package/modules/AGENTS.template.md +29 -11
  15. package/modules/bus/README.md +33 -25
  16. package/modules/bus/SKILLS/ubus/SKILL.md +19 -8
  17. package/modules/context/README.md +18 -40
  18. package/modules/context/SKILLS/uctx/SKILL.md +63 -1
  19. package/modules/online/SKILLS/ufoo-online/SKILL.md +144 -0
  20. package/package.json +25 -4
  21. package/scripts/import-pi-mono.js +124 -0
  22. package/scripts/postinstall.js +30 -0
  23. package/scripts/sync-claude-skills.sh +21 -0
  24. package/src/agent/cliRunner.js +554 -33
  25. package/src/agent/internalRunner.js +150 -56
  26. package/src/agent/launcher.js +754 -0
  27. package/src/agent/normalizeOutput.js +1 -1
  28. package/src/agent/notifier.js +340 -0
  29. package/src/agent/ptyRunner.js +847 -0
  30. package/src/agent/ptyWrapper.js +379 -0
  31. package/src/agent/readyDetector.js +175 -0
  32. package/src/agent/ucode.js +443 -0
  33. package/src/agent/ucodeBootstrap.js +113 -0
  34. package/src/agent/ucodeBuild.js +67 -0
  35. package/src/agent/ucodeDoctor.js +184 -0
  36. package/src/agent/ucodeRuntimeConfig.js +129 -0
  37. package/src/agent/ufooAgent.js +46 -42
  38. package/src/assistant/agent.js +260 -0
  39. package/src/assistant/bridge.js +172 -0
  40. package/src/assistant/engine.js +252 -0
  41. package/src/assistant/stdio.js +58 -0
  42. package/src/assistant/ufooEngineCli.js +306 -0
  43. package/src/bus/activate.js +172 -0
  44. package/src/bus/daemon.js +436 -0
  45. package/src/bus/index.js +842 -0
  46. package/src/bus/inject.js +315 -0
  47. package/src/bus/message.js +430 -0
  48. package/src/bus/nickname.js +88 -0
  49. package/src/bus/queue.js +136 -0
  50. package/src/bus/shake.js +26 -0
  51. package/src/bus/store.js +189 -0
  52. package/src/bus/subscriber.js +312 -0
  53. package/src/bus/utils.js +363 -0
  54. package/src/chat/agentBar.js +117 -0
  55. package/src/chat/agentDirectory.js +88 -0
  56. package/src/chat/agentSockets.js +225 -0
  57. package/src/chat/agentViewController.js +298 -0
  58. package/src/chat/chatLogController.js +115 -0
  59. package/src/chat/commandExecutor.js +700 -0
  60. package/src/chat/commands.js +132 -0
  61. package/src/chat/completionController.js +414 -0
  62. package/src/chat/cronScheduler.js +160 -0
  63. package/src/chat/daemonConnection.js +166 -0
  64. package/src/chat/daemonCoordinator.js +64 -0
  65. package/src/chat/daemonMessageRouter.js +257 -0
  66. package/src/chat/daemonReconnect.js +41 -0
  67. package/src/chat/daemonTransport.js +36 -0
  68. package/src/chat/daemonTransportDefaults.js +10 -0
  69. package/src/chat/dashboardKeyController.js +480 -0
  70. package/src/chat/dashboardView.js +154 -0
  71. package/src/chat/index.js +1011 -1392
  72. package/src/chat/inputHistoryController.js +105 -0
  73. package/src/chat/inputListenerController.js +304 -0
  74. package/src/chat/inputMath.js +104 -0
  75. package/src/chat/inputSubmitHandler.js +171 -0
  76. package/src/chat/layout.js +165 -0
  77. package/src/chat/pasteController.js +81 -0
  78. package/src/chat/rawKeyMap.js +42 -0
  79. package/src/chat/settingsController.js +132 -0
  80. package/src/chat/statusLineController.js +177 -0
  81. package/src/chat/streamTracker.js +138 -0
  82. package/src/chat/text.js +70 -0
  83. package/src/chat/transport.js +61 -0
  84. package/src/cli/busCoreCommands.js +59 -0
  85. package/src/cli/ctxCoreCommands.js +199 -0
  86. package/src/cli/onlineCoreCommands.js +379 -0
  87. package/src/cli.js +1162 -96
  88. package/src/code/README.md +29 -0
  89. package/src/code/UCODE_PROMPT.md +32 -0
  90. package/src/code/agent.js +1651 -0
  91. package/src/code/cli.js +158 -0
  92. package/src/code/config +0 -0
  93. package/src/code/dispatch.js +42 -0
  94. package/src/code/index.js +70 -0
  95. package/src/code/nativeRunner.js +1213 -0
  96. package/src/code/runtime.js +154 -0
  97. package/src/code/sessionStore.js +162 -0
  98. package/src/code/taskDecomposer.js +269 -0
  99. package/src/code/tools/bash.js +53 -0
  100. package/src/code/tools/common.js +42 -0
  101. package/src/code/tools/edit.js +70 -0
  102. package/src/code/tools/read.js +44 -0
  103. package/src/code/tools/write.js +35 -0
  104. package/src/code/tui.js +1580 -0
  105. package/src/config.js +56 -3
  106. package/src/context/decisions.js +324 -0
  107. package/src/context/doctor.js +183 -0
  108. package/src/context/index.js +55 -0
  109. package/src/context/sync.js +127 -0
  110. package/src/daemon/agentProcessManager.js +74 -0
  111. package/src/daemon/cronOps.js +241 -0
  112. package/src/daemon/index.js +998 -170
  113. package/src/daemon/ipcServer.js +99 -0
  114. package/src/daemon/ops.js +630 -48
  115. package/src/daemon/promptLoop.js +319 -0
  116. package/src/daemon/promptRequest.js +101 -0
  117. package/src/daemon/providerSessions.js +306 -0
  118. package/src/daemon/reporting.js +90 -0
  119. package/src/daemon/run.js +31 -1
  120. package/src/daemon/status.js +48 -8
  121. package/src/doctor/index.js +50 -0
  122. package/src/init/index.js +318 -0
  123. package/src/online/bridge.js +663 -0
  124. package/src/online/client.js +245 -0
  125. package/src/online/runner.js +253 -0
  126. package/src/online/server.js +992 -0
  127. package/src/online/tokens.js +103 -0
  128. package/src/report/store.js +331 -0
  129. package/src/shared/eventContract.js +35 -0
  130. package/src/shared/ptySocketContract.js +21 -0
  131. package/src/skills/index.js +159 -0
  132. package/src/status/index.js +285 -0
  133. package/src/terminal/adapterContract.js +87 -0
  134. package/src/terminal/adapterRouter.js +84 -0
  135. package/src/terminal/adapters/externalAdapter.js +14 -0
  136. package/src/terminal/adapters/internalAdapter.js +13 -0
  137. package/src/terminal/adapters/internalPtyAdapter.js +42 -0
  138. package/src/terminal/adapters/internalQueueAdapter.js +37 -0
  139. package/src/terminal/adapters/terminalAdapter.js +31 -0
  140. package/src/terminal/adapters/tmuxAdapter.js +30 -0
  141. package/src/terminal/detect.js +64 -0
  142. package/src/terminal/index.js +8 -0
  143. package/src/terminal/iterm2.js +126 -0
  144. package/src/ufoo/agentsStore.js +107 -0
  145. package/src/ufoo/paths.js +46 -0
  146. package/src/utils/banner.js +76 -0
  147. package/bin/uclaude +0 -65
  148. package/bin/ucodex +0 -65
  149. package/modules/bus/scripts/bus-alert.sh +0 -185
  150. package/modules/bus/scripts/bus-listen.sh +0 -117
  151. package/modules/context/ASSUMPTIONS.md +0 -7
  152. package/modules/context/CONSTRAINTS.md +0 -7
  153. package/modules/context/CONTEXT-STRUCTURE.md +0 -49
  154. package/modules/context/DECISION-PROTOCOL.md +0 -62
  155. package/modules/context/HANDOFF.md +0 -33
  156. package/modules/context/RULES.md +0 -15
  157. package/modules/context/SKILLS/README.md +0 -14
  158. package/modules/context/SYSTEM.md +0 -18
  159. package/modules/context/TEMPLATES/assumptions.md +0 -4
  160. package/modules/context/TEMPLATES/constraints.md +0 -4
  161. package/modules/context/TEMPLATES/decision.md +0 -16
  162. package/modules/context/TEMPLATES/project-context-readme.md +0 -6
  163. package/modules/context/TEMPLATES/system.md +0 -3
  164. package/modules/context/TEMPLATES/terminology.md +0 -4
  165. package/modules/context/TERMINOLOGY.md +0 -10
  166. package/scripts/banner.sh +0 -89
  167. package/scripts/bus-alert.sh +0 -6
  168. package/scripts/bus-autotrigger.sh +0 -6
  169. package/scripts/bus-daemon.sh +0 -231
  170. package/scripts/bus-inject.sh +0 -144
  171. package/scripts/bus-listen.sh +0 -6
  172. package/scripts/bus.sh +0 -984
  173. package/scripts/context-decisions.sh +0 -167
  174. package/scripts/context-doctor.sh +0 -72
  175. package/scripts/context-lint.sh +0 -110
  176. package/scripts/doctor.sh +0 -22
  177. package/scripts/init.sh +0 -247
  178. package/scripts/skills.sh +0 -113
  179. package/scripts/status.sh +0 -125
@@ -1,231 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- # bus-daemon.sh
5
- # Daemon that watches for new messages and injects /bus into target terminals.
6
- #
7
- # Usage:
8
- # bash scripts/bus-daemon.sh [--interval <seconds>] [--daemon]
9
- #
10
- # This script monitors ALL subscribers' pending queues and injects /bus
11
- # into their corresponding Terminal.app tabs when new messages arrive.
12
- #
13
- # Requirements:
14
- # - macOS Accessibility permission for Terminal.app
15
- # - Each subscriber's terminal should have title containing [bus:<instance-id>]
16
-
17
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18
- BUS_DIR=".ufoo/bus"
19
- INTERVAL=2
20
- DAEMON_MODE=0
21
- PID_FILE="$BUS_DIR/.daemon.pid"
22
- LOG_FILE="$BUS_DIR/logs/daemon.log"
23
-
24
- usage() {
25
- cat <<'USAGE'
26
- bus-daemon.sh - Watch for new messages and inject /bus
27
-
28
- Usage:
29
- bash scripts/bus-daemon.sh [options]
30
-
31
- Options:
32
- --interval <n> Poll interval in seconds (default: 2)
33
- --daemon Run in background
34
- --stop Stop running daemon
35
- --status Check daemon status
36
- -h, --help Show this help
37
-
38
- Notes:
39
- - Requires macOS Accessibility permission
40
- - Terminals must have title containing [bus:<instance-id>]
41
- - Use `ufoo bus join` to set terminal title
42
- USAGE
43
- }
44
-
45
- # Handle --help before other parsing
46
- if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
47
- usage
48
- exit 0
49
- fi
50
-
51
- while [[ $# -gt 0 ]]; do
52
- case "$1" in
53
- --interval)
54
- INTERVAL="$2"
55
- shift 2
56
- ;;
57
- --daemon)
58
- DAEMON_MODE=1
59
- shift
60
- ;;
61
- --stop)
62
- if [[ -f "$PID_FILE" ]]; then
63
- pid="$(cat "$PID_FILE" 2>/dev/null || true)"
64
- if [[ -n "$pid" ]]; then
65
- kill "$pid" 2>/dev/null && echo "[daemon] Stopped (pid=$pid)" || echo "[daemon] Not running"
66
- fi
67
- rm -f "$PID_FILE"
68
- else
69
- echo "[daemon] Not running"
70
- fi
71
- exit 0
72
- ;;
73
- --status)
74
- if [[ -f "$PID_FILE" ]]; then
75
- pid="$(cat "$PID_FILE" 2>/dev/null || true)"
76
- if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
77
- echo "[daemon] Running (pid=$pid)"
78
- else
79
- echo "[daemon] Not running (stale pid file)"
80
- rm -f "$PID_FILE"
81
- fi
82
- else
83
- echo "[daemon] Not running"
84
- fi
85
- exit 0
86
- ;;
87
- *)
88
- echo "Unknown option: $1" >&2
89
- usage >&2
90
- exit 1
91
- ;;
92
- esac
93
- done
94
-
95
- if [[ ! -d "$BUS_DIR" ]]; then
96
- echo "[daemon] Error: $BUS_DIR not found. Run ufoo init first." >&2
97
- exit 1
98
- fi
99
-
100
- mkdir -p "$BUS_DIR/logs"
101
-
102
- if [[ "$DAEMON_MODE" == "1" ]]; then
103
- # Check if already running
104
- if [[ -f "$PID_FILE" ]]; then
105
- existing="$(cat "$PID_FILE" 2>/dev/null || true)"
106
- if [[ -n "$existing" ]] && kill -0 "$existing" 2>/dev/null; then
107
- echo "[daemon] Already running (pid=$existing)"
108
- exit 0
109
- fi
110
- fi
111
-
112
- echo "[daemon] Starting in background (log: $LOG_FILE)"
113
- nohup bash "$0" --interval "$INTERVAL" >> "$LOG_FILE" 2>&1 &
114
- echo $! > "$PID_FILE"
115
- echo "[daemon] Started (pid=$!)"
116
- exit 0
117
- fi
118
-
119
- # Record PID
120
- echo $$ > "$PID_FILE"
121
- trap 'rm -f "$PID_FILE" 2>/dev/null || true; rm -rf "$COUNTS_DIR" 2>/dev/null || true' EXIT
122
-
123
- echo "[daemon] Started (pid=$$, interval=${INTERVAL}s)"
124
- echo "[daemon] Watching: $BUS_DIR/queues/*/pending.jsonl"
125
-
126
- # Use temp directory to track last known counts (bash 3.x compatible)
127
- COUNTS_DIR="$BUS_DIR/.daemon-counts.$$"
128
- mkdir -p "$COUNTS_DIR"
129
-
130
- get_last_count() {
131
- local safe_name="$1"
132
- local count_file="$COUNTS_DIR/$safe_name"
133
- if [[ -f "$count_file" ]]; then
134
- cat "$count_file"
135
- else
136
- echo "0"
137
- fi
138
- }
139
-
140
- set_last_count() {
141
- local safe_name="$1"
142
- local count="$2"
143
- echo "$count" > "$COUNTS_DIR/$safe_name"
144
- }
145
-
146
- # Cleanup dead agents (check PID and mark offline)
147
- cleanup_dead_agents() {
148
- if [[ ! -f "$BUS_DIR/bus.json" ]]; then
149
- return
150
- fi
151
-
152
- local changed=0
153
- local tmp_file
154
- tmp_file=$(mktemp)
155
-
156
- # Get all active subscribers with their PIDs
157
- while IFS='|' read -r subscriber pid; do
158
- [[ -z "$subscriber" || -z "$pid" ]] && continue
159
-
160
- # Check if PID is still running AND is a claude/codex/node process
161
- local proc_cmd
162
- proc_cmd=$(ps -p "$pid" -o comm= 2>/dev/null || true)
163
- if [[ -z "$proc_cmd" ]] || ! echo "$proc_cmd" | grep -qiE "(claude|codex|node)"; then
164
- echo "[daemon] $(date '+%H:%M:%S') Agent $subscriber (pid=$pid) is dead, marking offline"
165
-
166
- # Mark as offline in bus.json
167
- jq --arg name "$subscriber" \
168
- '.subscribers[$name].status = "offline"' \
169
- "$BUS_DIR/bus.json" > "$tmp_file" && mv "$tmp_file" "$BUS_DIR/bus.json"
170
- tmp_file=$(mktemp)
171
-
172
- # Clean up queue directory
173
- local safe_name="${subscriber//:/_}"
174
- rm -rf "$BUS_DIR/queues/${safe_name}" 2>/dev/null || true
175
- rm -f "$BUS_DIR/offsets/${safe_name}.offset" 2>/dev/null || true
176
-
177
- changed=1
178
- fi
179
- done < <(jq -r '.subscribers | to_entries[] | select(.value.status == "active") | "\(.key)|\(.value.pid)"' "$BUS_DIR/bus.json" 2>/dev/null)
180
-
181
- rm -f "$tmp_file" 2>/dev/null || true
182
- }
183
-
184
- CLEANUP_COUNTER=0
185
- CLEANUP_INTERVAL=5 # Run cleanup every 5 cycles (10 seconds with default interval)
186
-
187
- while true; do
188
- # Periodic cleanup of dead agents
189
- ((CLEANUP_COUNTER++)) || true
190
- if [[ $CLEANUP_COUNTER -ge $CLEANUP_INTERVAL ]]; then
191
- cleanup_dead_agents
192
- CLEANUP_COUNTER=0
193
- fi
194
- # Find all subscriber queue files
195
- for queue_file in "$BUS_DIR/queues"/*/pending.jsonl; do
196
- if [[ ! -f "$queue_file" ]]; then
197
- continue
198
- fi
199
-
200
- # Extract subscriber from path: .ufoo/bus/queues/claude-code_abc123/pending.jsonl
201
- dir_name="$(basename "$(dirname "$queue_file")")"
202
- # Convert back to subscriber format: claude-code_abc123 -> claude-code:abc123
203
- subscriber="${dir_name/_/:}"
204
-
205
- # Get current count
206
- if [[ -s "$queue_file" ]]; then
207
- count="$(wc -l < "$queue_file" | tr -d ' ')"
208
- else
209
- count=0
210
- fi
211
-
212
- # Get last known count
213
- last="$(get_last_count "$dir_name")"
214
-
215
- # If count increased, inject /bus
216
- if [[ "$count" -gt "$last" ]]; then
217
- echo "[daemon] $(date '+%H:%M:%S') New message for $subscriber ($last -> $count)"
218
-
219
- # Try to inject
220
- if bash "$SCRIPT_DIR/bus-inject.sh" "$subscriber" 2>&1; then
221
- echo "[daemon] Injected /bus into $subscriber"
222
- else
223
- echo "[daemon] Failed to inject (window not found or no permission)"
224
- fi
225
- fi
226
-
227
- set_last_count "$dir_name" "$count"
228
- done
229
-
230
- sleep "$INTERVAL"
231
- done
@@ -1,144 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- # bus-inject.sh
5
- # Inject `/ubus` command into Terminal.app tab.
6
- #
7
- # Usage:
8
- # bash scripts/bus-inject.sh <subscriber-id>
9
- #
10
- # Method:
11
- # - Clipboard paste (Cmd+V) to bypass IME
12
- # - Accessibility (System Events) for Escape + Paste + Enter
13
- #
14
- # Requirements:
15
- # - macOS Accessibility permission for Terminal (first run will prompt)
16
- # - Subscriber must have joined via `claude-bus` wrapper
17
-
18
- BUS_DIR=".ufoo/bus"
19
- SUBSCRIBER="${1:-}"
20
-
21
- if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
22
- echo "Usage: bus-inject.sh <subscriber-id>"
23
- echo ""
24
- echo "Injects '/ubus' + Enter into Terminal.app tab by tty device."
25
- echo "The subscriber must have joined from that terminal first."
26
- exit 0
27
- fi
28
-
29
- if [[ -z "$SUBSCRIBER" ]]; then
30
- echo "Error: subscriber ID required" >&2
31
- echo "Usage: bus-inject.sh <subscriber-id>" >&2
32
- exit 1
33
- fi
34
-
35
- # Convert subscriber to safe name
36
- safe_name="${SUBSCRIBER//:/_}"
37
- tty_file="$BUS_DIR/queues/${safe_name}/tty"
38
-
39
- if [[ ! -f "$tty_file" ]]; then
40
- echo "[inject] Error: No tty recorded for $SUBSCRIBER" >&2
41
- echo "[inject] Make sure to run 'ufoo bus join' from the target terminal first" >&2
42
- exit 1
43
- fi
44
-
45
- TARGET_TTY=$(cat "$tty_file")
46
- echo "[inject] Looking for Terminal tab with tty: $TARGET_TTY"
47
-
48
- # Determine command based on agent type
49
- # codex uses "ubus" without slash, claude-code uses "/ubus"
50
- if [[ "$SUBSCRIBER" == codex:* ]]; then
51
- INJECT_CMD="ubus"
52
- else
53
- INJECT_CMD="/ubus"
54
- fi
55
-
56
- # Detect terminal type from tty path or environment
57
- # iTerm2 uses "write text", Terminal.app uses "do script"
58
-
59
- # Check if iTerm2 is running and has this tty
60
- USE_ITERM=0
61
- if pgrep -q "iTerm2"; then
62
- # Check if iTerm2 has a session with this tty
63
- if osascript -e 'tell application "iTerm2" to get tty of current session of current window' 2>/dev/null | grep -q "$TARGET_TTY"; then
64
- USE_ITERM=1
65
- fi
66
- fi
67
-
68
- if [[ "$USE_ITERM" == "1" ]]; then
69
- echo "[inject] Using iTerm2 write text method"
70
- osascript <<EOF
71
- tell application "iTerm2"
72
- activate
73
- repeat with w in windows
74
- repeat with t in tabs of w
75
- repeat with s in sessions of t
76
- try
77
- if tty of s is "$TARGET_TTY" then
78
- select s
79
- -- Use write text which includes newline automatically
80
- write text "$INJECT_CMD" to s
81
- return
82
- end if
83
- end try
84
- end repeat
85
- end repeat
86
- end repeat
87
- error "No iTerm2 session found with tty: $TARGET_TTY"
88
- end tell
89
- EOF
90
- else
91
- echo "[inject] Using Terminal.app keystroke method (for interactive apps like Codex)"
92
- osascript <<EOF
93
- tell application "Terminal"
94
- set targetWindow to missing value
95
- set targetTab to missing value
96
-
97
- repeat with w in windows
98
- repeat with t in tabs of w
99
- try
100
- if tty of t is "$TARGET_TTY" then
101
- set targetWindow to w
102
- set targetTab to t
103
- exit repeat
104
- end if
105
- end try
106
- end repeat
107
- if targetTab is not missing value then exit repeat
108
- end repeat
109
-
110
- if targetTab is missing value then
111
- error "No Terminal tab found with tty: $TARGET_TTY"
112
- end if
113
-
114
- -- Activate and bring to front
115
- activate
116
- set selected tab of targetWindow to targetTab
117
- set index of targetWindow to 1
118
- end tell
119
-
120
- -- Save current clipboard, set /ubus, paste, restore
121
- set oldClipboard to the clipboard
122
-
123
- set the clipboard to "$INJECT_CMD"
124
- delay 0.1
125
-
126
- tell application "System Events"
127
- tell process "Terminal"
128
- -- Escape to ensure input mode
129
- key code 53
130
- delay 0.1
131
- -- Cmd+V to paste
132
- keystroke "v" using command down
133
- delay 0.2
134
- -- Enter (Return key)
135
- keystroke return
136
- end tell
137
- end tell
138
-
139
- delay 0.2
140
- set the clipboard to oldClipboard
141
- EOF
142
- fi
143
-
144
- echo "[inject] Done"
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
- exec bash "$repo_root/modules/bus/scripts/bus-listen.sh" "$@"
6
-