u-foo 1.0.6 → 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 (149) hide show
  1. package/README.md +44 -4
  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 +11 -2
  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 +154 -0
  64. package/src/chat/index.js +935 -2909
  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 +132 -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 +1580 -0
  98. package/src/config.js +47 -1
  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 +661 -488
  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
@@ -0,0 +1,84 @@
1
+ const {
2
+ createTerminalCapabilities,
3
+ assertTerminalAdapterContract,
4
+ } = require("./adapterContract");
5
+ const { createTerminalAdapter } = require("./adapters/terminalAdapter");
6
+ const { createTmuxAdapter } = require("./adapters/tmuxAdapter");
7
+ const { createInternalQueueAdapter } = require("./adapters/internalQueueAdapter");
8
+ const { createInternalPtyAdapter } = require("./adapters/internalPtyAdapter");
9
+
10
+ function createTerminalAdapterRouter(options = {}) {
11
+ const {
12
+ activateAgent = () => {},
13
+ activateTerminal = null,
14
+ activateTmux = null,
15
+ sendRaw = () => {},
16
+ sendResize = () => {},
17
+ requestSnapshot = () => false,
18
+ } = options;
19
+
20
+ function createAdapter({ capabilities, handlers = {} }) {
21
+ const adapter = {
22
+ capabilities,
23
+ connect: handlers.connect || (async () => false),
24
+ disconnect: handlers.disconnect || (async () => false),
25
+ send: handlers.send || (() => false),
26
+ sendRaw: handlers.sendRaw || (() => false),
27
+ resize: handlers.resize || (() => false),
28
+ snapshot: handlers.snapshot || (() => false),
29
+ subscribe: handlers.subscribe || (() => false),
30
+ activate: handlers.activate || (() => false),
31
+ getState: handlers.getState || (() => ({})),
32
+ };
33
+ assertTerminalAdapterContract(adapter);
34
+ return adapter;
35
+ }
36
+
37
+ function getAdapter(params = {}) {
38
+ const { launchMode = "", agentId = "" } = params;
39
+
40
+ if (launchMode === "terminal") {
41
+ return createTerminalAdapter({
42
+ agentId,
43
+ activateAgent: activateTerminal || activateAgent,
44
+ createAdapter,
45
+ });
46
+ }
47
+
48
+ if (launchMode === "tmux") {
49
+ return createTmuxAdapter({
50
+ agentId,
51
+ activateAgent: activateTmux || activateAgent,
52
+ createAdapter,
53
+ });
54
+ }
55
+
56
+ if (launchMode === "internal-pty") {
57
+ return createInternalPtyAdapter({
58
+ sendRaw,
59
+ sendResize,
60
+ requestSnapshot,
61
+ createAdapter,
62
+ });
63
+ }
64
+
65
+ if (launchMode === "internal") {
66
+ return createInternalQueueAdapter({
67
+ sendRaw,
68
+ sendResize,
69
+ requestSnapshot,
70
+ createAdapter,
71
+ });
72
+ }
73
+
74
+ return createAdapter({ capabilities: createTerminalCapabilities() });
75
+ }
76
+
77
+ return {
78
+ getAdapter,
79
+ };
80
+ }
81
+
82
+ module.exports = {
83
+ createTerminalAdapterRouter,
84
+ };
@@ -0,0 +1,14 @@
1
+ const { createTerminalAdapter } = require("./terminalAdapter");
2
+ const { createTmuxAdapter } = require("./tmuxAdapter");
3
+
4
+ function createExternalAdapter(options = {}) {
5
+ const mode = options.mode || "terminal";
6
+ if (mode === "tmux") {
7
+ return createTmuxAdapter(options);
8
+ }
9
+ return createTerminalAdapter(options);
10
+ }
11
+
12
+ module.exports = {
13
+ createExternalAdapter,
14
+ };
@@ -0,0 +1,13 @@
1
+ const { createInternalPtyAdapter } = require("./internalPtyAdapter");
2
+ const { createInternalQueueAdapter } = require("./internalQueueAdapter");
3
+
4
+ function createInternalAdapter(options = {}) {
5
+ if (options.usePty) {
6
+ return createInternalPtyAdapter(options);
7
+ }
8
+ return createInternalQueueAdapter(options);
9
+ }
10
+
11
+ module.exports = {
12
+ createInternalAdapter,
13
+ };
@@ -0,0 +1,42 @@
1
+ const { createTerminalCapabilities } = require("../adapterContract");
2
+
3
+ function createInternalPtyAdapter(options = {}) {
4
+ const {
5
+ sendRaw = () => {},
6
+ sendResize = () => {},
7
+ requestSnapshot = () => false,
8
+ createAdapter = () => {},
9
+ } = options;
10
+
11
+ const capabilities = createTerminalCapabilities({
12
+ supportsInternalQueueLoop: true,
13
+ supportsSocketProtocol: true,
14
+ supportsSubscribeFull: true,
15
+ supportsSubscribeScreen: true,
16
+ supportsSnapshot: true,
17
+ });
18
+
19
+ return createAdapter({
20
+ capabilities,
21
+ handlers: {
22
+ send: (data) => {
23
+ sendRaw(data);
24
+ return true;
25
+ },
26
+ sendRaw: (data) => {
27
+ sendRaw(data);
28
+ return true;
29
+ },
30
+ resize: (cols, rows) => {
31
+ sendResize(cols, rows);
32
+ return true;
33
+ },
34
+ snapshot: () => Boolean(requestSnapshot("screen")),
35
+ subscribe: () => Boolean(requestSnapshot("full")),
36
+ },
37
+ });
38
+ }
39
+
40
+ module.exports = {
41
+ createInternalPtyAdapter,
42
+ };
@@ -0,0 +1,37 @@
1
+ const { createTerminalCapabilities } = require("../adapterContract");
2
+
3
+ function createInternalQueueAdapter(options = {}) {
4
+ const {
5
+ sendRaw = () => {},
6
+ createAdapter = () => {},
7
+ } = options;
8
+
9
+ const capabilities = createTerminalCapabilities({
10
+ supportsInternalQueueLoop: true,
11
+ supportsSocketProtocol: false,
12
+ supportsSubscribeFull: false,
13
+ supportsSubscribeScreen: false,
14
+ supportsSnapshot: false,
15
+ });
16
+
17
+ return createAdapter({
18
+ capabilities,
19
+ handlers: {
20
+ send: (data) => {
21
+ sendRaw(data);
22
+ return true;
23
+ },
24
+ sendRaw: (data) => {
25
+ sendRaw(data);
26
+ return true;
27
+ },
28
+ resize: () => false,
29
+ snapshot: () => false,
30
+ subscribe: () => false,
31
+ },
32
+ });
33
+ }
34
+
35
+ module.exports = {
36
+ createInternalQueueAdapter,
37
+ };
@@ -0,0 +1,31 @@
1
+ const { createTerminalCapabilities } = require("../adapterContract");
2
+
3
+ function createTerminalAdapter(options = {}) {
4
+ const {
5
+ agentId = "",
6
+ activateAgent = () => {},
7
+ createAdapter = () => {},
8
+ } = options;
9
+
10
+ const capabilities = createTerminalCapabilities({
11
+ supportsActivate: true,
12
+ supportsReplay: true,
13
+ supportsWindowClose: true,
14
+ supportsNotifierInjector: true,
15
+ supportsSessionReuse: true,
16
+ });
17
+
18
+ return createAdapter({
19
+ capabilities,
20
+ handlers: {
21
+ activate: () => {
22
+ activateAgent(agentId);
23
+ return true;
24
+ },
25
+ },
26
+ });
27
+ }
28
+
29
+ module.exports = {
30
+ createTerminalAdapter,
31
+ };
@@ -0,0 +1,30 @@
1
+ const { createTerminalCapabilities } = require("../adapterContract");
2
+
3
+ function createTmuxAdapter(options = {}) {
4
+ const {
5
+ agentId = "",
6
+ activateAgent = () => {},
7
+ createAdapter = () => {},
8
+ } = options;
9
+
10
+ const capabilities = createTerminalCapabilities({
11
+ supportsActivate: true,
12
+ supportsReplay: false,
13
+ supportsNotifierInjector: true,
14
+ supportsSessionReuse: true,
15
+ });
16
+
17
+ return createAdapter({
18
+ capabilities,
19
+ handlers: {
20
+ activate: () => {
21
+ activateAgent(agentId);
22
+ return true;
23
+ },
24
+ },
25
+ });
26
+ }
27
+
28
+ module.exports = {
29
+ createTmuxAdapter,
30
+ };
@@ -2,12 +2,78 @@ const { getTimestamp, readJSON, writeJSON } = require("../bus/utils");
2
2
 
3
3
  const AGENTS_SCHEMA_VERSION = 1;
4
4
 
5
+ function toSafeString(value) {
6
+ return typeof value === "string" ? value : "";
7
+ }
8
+
9
+ function normalizeAgentEntry(id, meta = {}) {
10
+ let normalizedId = String(id || "");
11
+ const doublePrefix = normalizedId.match(/^([^:]+):\1:(.+)$/);
12
+ if (doublePrefix) {
13
+ normalizedId = `${doublePrefix[1]}:${doublePrefix[2]}`;
14
+ }
15
+ const underscorePrefix = normalizedId.match(/^([^:]+):\1_(.+)$/);
16
+ if (underscorePrefix) {
17
+ normalizedId = `${underscorePrefix[1]}:${underscorePrefix[2]}`;
18
+ }
19
+
20
+ const normalizedMeta = meta && typeof meta === "object" ? { ...meta } : {};
21
+ if (normalizedMeta.nickname && typeof normalizedMeta.nickname === "object") {
22
+ const leakedOptions = normalizedMeta.nickname;
23
+ normalizedMeta.nickname = "";
24
+ if (!normalizedMeta.launch_mode) {
25
+ normalizedMeta.launch_mode = toSafeString(leakedOptions.launchMode);
26
+ }
27
+ if (!normalizedMeta.tmux_pane) {
28
+ normalizedMeta.tmux_pane = toSafeString(leakedOptions.tmuxPane);
29
+ }
30
+ if (!normalizedMeta.tty) {
31
+ normalizedMeta.tty = toSafeString(leakedOptions.tty);
32
+ }
33
+ if (
34
+ (!Number.isFinite(Number(normalizedMeta.pid)) || Number(normalizedMeta.pid) <= 0)
35
+ && Number.isFinite(leakedOptions.parentPid)
36
+ && leakedOptions.parentPid > 0
37
+ ) {
38
+ normalizedMeta.pid = leakedOptions.parentPid;
39
+ }
40
+ }
41
+
42
+ return { id: normalizedId, meta: normalizedMeta };
43
+ }
44
+
45
+ function normalizeAgentsMap(agents = {}) {
46
+ const out = {};
47
+ for (const [rawId, rawMeta] of Object.entries(agents || {})) {
48
+ const { id, meta } = normalizeAgentEntry(rawId, rawMeta);
49
+ if (!id) continue;
50
+ if (!out[id]) {
51
+ out[id] = meta;
52
+ continue;
53
+ }
54
+ const current = out[id] || {};
55
+ const incoming = meta || {};
56
+ const currentActive = current.status === "active";
57
+ const incomingActive = incoming.status === "active";
58
+ if (incomingActive && !currentActive) {
59
+ out[id] = incoming;
60
+ continue;
61
+ }
62
+ const currentSeen = String(current.last_seen || current.joined_at || "");
63
+ const incomingSeen = String(incoming.last_seen || incoming.joined_at || "");
64
+ if (incomingSeen > currentSeen) {
65
+ out[id] = incoming;
66
+ }
67
+ }
68
+ return out;
69
+ }
70
+
5
71
  function normalizeAgentsData(data) {
6
72
  const base = data && typeof data === "object" ? { ...data } : {};
7
73
  const { subscribers: _legacy, ...rest } = base;
8
- const agents = base.agents && typeof base.agents === "object"
9
- ? base.agents
10
- : {};
74
+ const agents = normalizeAgentsMap(
75
+ base.agents && typeof base.agents === "object" ? base.agents : {}
76
+ );
11
77
  const createdAt = typeof base.created_at === "string" && base.created_at
12
78
  ? base.created_at
13
79
  : getTimestamp();
@@ -13,12 +13,15 @@ function showBanner(options) {
13
13
  "▀▀▀ ▀ ▀▀▀ ▀▀▀",
14
14
  ];
15
15
 
16
+ // Normalize agent type display name
17
+ const displayAgentType = agentType === "ufoo-code" ? "ucode" : agentType;
18
+
16
19
  // 准备右侧信息行
17
20
  const infoLines = [];
18
21
  if (nickname) {
19
22
  infoLines.push(`${chalk.dim("Nickname:")} ${chalk.cyan.bold(nickname)}`);
20
23
  }
21
- infoLines.push(`${chalk.dim("Agent:")} ${chalk.green.bold(agentType)}${chalk.dim(":")}${chalk.yellow(sessionId)}`);
24
+ infoLines.push(`${chalk.dim("Agent:")} ${chalk.green.bold(displayAgentType)}${chalk.dim(":")}${chalk.yellow(sessionId)}`);
22
25
  if (daemonStatus) {
23
26
  const statusColor = daemonStatus === "running" ? chalk.green : chalk.blue;
24
27
  infoLines.push(`${chalk.dim("Daemon:")} ${statusColor(daemonStatus)}`);
@@ -57,7 +60,7 @@ function showUfooBanner(options = {}) {
57
60
  const infoLines = [
58
61
  `${chalk.cyan.bold(`v${version}`)} ${chalk.gray("Multi-Agent Workspace Protocol")}`,
59
62
  "",
60
- chalk.dim("uclaude") + chalk.gray(" · ") + chalk.dim("ucodex") + chalk.gray(" · ") + chalk.dim("ufoo init") + chalk.gray(" · ") + chalk.dim("ufoo ctx") + chalk.gray(" · ") + chalk.dim("ufoo bus"),
63
+ chalk.dim("uclaude") + chalk.gray(" · ") + chalk.dim("ucodex") + chalk.gray(" · ") + chalk.dim("ucode") + chalk.gray(" · ") + chalk.dim("ufoo init") + chalk.gray(" · ") + chalk.dim("ufoo ctx") + chalk.gray(" · ") + chalk.dim("ufoo bus"),
61
64
  ];
62
65
 
63
66
  // 输出:Logo 和信息并排显示
@@ -1,46 +0,0 @@
1
- # 已迁移到 JavaScript 的脚本
2
-
3
- 这些 bash 脚本已经完全迁移到 JavaScript 模块。
4
-
5
- ## 迁移对照表
6
-
7
- | Bash 脚本 | JavaScript 模块 | 状态 |
8
- |----------|----------------|------|
9
- | `bus.sh` | `src/bus/index.js` + 7个子模块 | ✅ 完全替换 |
10
- | `bus-daemon.sh` | `src/bus/daemon.js` | ✅ 完全替换 |
11
- | `bus-inject.sh` | `src/bus/inject.js` | ✅ 完全替换 |
12
- | `status.sh` | `src/status/index.js` | ✅ 完全替换 |
13
- | `skills.sh` | `src/skills/index.js` | ✅ 完全替换 |
14
- | `init.sh` | `src/init/index.js` | ✅ 完全替换 |
15
-
16
- ## 迁移完成日期
17
-
18
- 2026-02-04
19
-
20
- ## 使用方式
21
-
22
- 所有命令接口保持不变,直接使用即可:
23
-
24
- ```bash
25
- ufoo bus status
26
- ufoo status
27
- ufoo skills list
28
- ufoo init
29
- ```
30
-
31
- ## 保留原因
32
-
33
- 这些脚本被归档保留用于:
34
- 1. 历史参考
35
- 2. 性能对比
36
- 3. 回退备份(如有必要)
37
-
38
- ## 性能对比
39
-
40
- | 指标 | Bash | JavaScript | 差异 |
41
- |------|------|------------|------|
42
- | 消息延迟 | 45ms | 51ms | +13% |
43
- | 并发安全 | ✅ | ✅ | 相同 |
44
- | 功能完整 | 100% | 100% | 相同 |
45
-
46
- 性能差异在可接受范围内(<15%),换取更好的可维护性和跨平台支持。
@@ -1,89 +0,0 @@
1
- #!/usr/bin/env bash
2
- # banner.sh - TUI startup banner for ufoo agents
3
-
4
- # Colors
5
- RST='\033[0m'
6
- BLD='\033[1m'
7
- DIM='\033[2m'
8
- CYN='\033[0;36m'
9
- GRN='\033[0;32m'
10
- MAG='\033[0;35m'
11
- WHT='\033[1;37m'
12
- YLW='\033[0;33m'
13
-
14
- show_banner() {
15
- local agent_type="${1:-claude}"
16
- local session_id="${2:-unknown}"
17
- local subscriber="${3:-}"
18
- local daemon_status="${4:-}"
19
-
20
- local ACOL
21
- if [[ "$agent_type" == "codex" ]]; then
22
- ACOL="$GRN"
23
- else
24
- ACOL="$MAG"
25
- fi
26
-
27
- # Width matches Codex CLI (inner content = 52)
28
- local INNER=52
29
- local W=$INNER
30
-
31
- # Helper: print line with exact padding
32
- line() {
33
- local prefix="$1"
34
- local value="$2"
35
- local color="$3"
36
- local prefix_len=${#prefix}
37
- local value_len=${#value}
38
- local pad_len=$((INNER - prefix_len - value_len))
39
- printf "${DIM}│${RST}${prefix}${color}${value}${RST}"
40
- printf "%${pad_len}s" ""
41
- printf "${DIM}│${RST}\n"
42
- }
43
-
44
- echo ""
45
- printf "${DIM}╭"; printf '─%.0s' $(seq 1 $W); printf "╮${RST}\n"
46
-
47
- # Title line with icon (compute padding from plain text lengths)
48
- local icon_plain="<○>"
49
- local title="UFOO · Multi-Agent Protocol"
50
- local title_pad=$((INNER - 1 - ${#icon_plain} - 1 - ${#title}))
51
- printf "${DIM}│${RST} ${WHT}${icon_plain}${RST} ${CYN}${BLD}UFOO${RST}${DIM} · Multi-Agent Protocol${RST}"
52
- printf "%${title_pad}s" ""
53
- printf "${DIM}│${RST}\n"
54
-
55
- printf "${DIM}├"; printf '─%.0s' $(seq 1 $W); printf "┤${RST}\n"
56
-
57
- # Agent
58
- if [[ -n "$subscriber" ]]; then
59
- local sub="$subscriber"
60
- [[ ${#sub} -gt 36 ]] && sub="${sub:0:33}..."
61
- line " Agent " "$sub" "${ACOL}${BLD}"
62
- fi
63
-
64
- # Daemon
65
- if [[ -n "$daemon_status" ]]; then
66
- line " Daemon " "$daemon_status" "${GRN}"
67
- fi
68
-
69
- # Online agents (daemon handles cleanup of dead agents)
70
- if [[ -f ".ufoo/bus/bus.json" ]]; then
71
- local online
72
- online=$(jq -r '.subscribers | to_entries[] | select(.value.status == "active") | .key' .ufoo/bus/bus.json 2>/dev/null | grep -v "^${subscriber}$" 2>/dev/null | head -5 || true)
73
- if [[ -n "$online" ]]; then
74
- printf "${DIM}├"; printf '─%.0s' $(seq 1 $W); printf "┤${RST}\n"
75
- line " Online " "" ""
76
- while IFS= read -r agent; do
77
- [[ -z "$agent" ]] && continue
78
- local a="$agent"
79
- [[ ${#a} -gt 44 ]] && a="${a:0:41}..."
80
- line " · " "$a" "${YLW}"
81
- done <<< "$online"
82
- fi
83
- fi
84
-
85
- printf "${DIM}╰"; printf '─%.0s' $(seq 1 $W); printf "╯${RST}\n"
86
- echo ""
87
- }
88
-
89
- export -f show_banner 2>/dev/null || true
@@ -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-alert.sh" "$@"
6
-
@@ -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-autotrigger.sh" "$@"
6
-