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
@@ -0,0 +1,318 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ /**
5
+ * ufoo 初始化管理
6
+ */
7
+ class UfooInit {
8
+ constructor(repoRoot) {
9
+ this.repoRoot = repoRoot;
10
+ this.contextMod = path.join(repoRoot, "modules", "context");
11
+ this.busMod = path.join(repoRoot, "modules", "bus");
12
+ this.resourcesMod = path.join(repoRoot, "modules", "resources");
13
+ this.agentsTemplate = path.join(repoRoot, "modules", "AGENTS.template.md");
14
+ }
15
+
16
+ /**
17
+ * 初始化项目
18
+ */
19
+ async init(options = {}) {
20
+ const modules = (options.modules || "context").split(",");
21
+ const project = options.project || process.cwd();
22
+
23
+ console.log("=== ufoo init ===");
24
+ console.log(`Project directory: ${project}`);
25
+ console.log(`Modules: ${modules.join(", ")}`);
26
+ console.log();
27
+
28
+ // 确保 AGENTS.md 和 CLAUDE.md 存在
29
+ this.ensureAgentsFiles(project);
30
+
31
+ // 初始化核心
32
+ this.initCore(project);
33
+
34
+ // 初始化 AGENTS.md 模板
35
+ this.injectAgentsTemplate(project);
36
+
37
+ // 初始化各模块
38
+ for (const module of modules) {
39
+ switch (module.trim()) {
40
+ case "context":
41
+ this.initContext(project);
42
+ break;
43
+ case "bus":
44
+ await this.initBus(project);
45
+ break;
46
+ case "resources":
47
+ this.initResources(project);
48
+ break;
49
+ default:
50
+ console.error(`Unknown module: ${module}`);
51
+ }
52
+ }
53
+
54
+ console.log();
55
+ console.log("✓ Initialization complete");
56
+ }
57
+
58
+ /**
59
+ * 确保 AGENTS.md 和 CLAUDE.md 存在
60
+ */
61
+ ensureAgentsFiles(project) {
62
+ const agentsFile = path.join(project, "AGENTS.md");
63
+ const claudeFile = path.join(project, "CLAUDE.md");
64
+
65
+ // 创建 AGENTS.md(如果不存在)
66
+ if (!fs.existsSync(agentsFile)) {
67
+ const content = `# Project Instructions
68
+
69
+ \`CLAUDE.md\` points to this file. Please keep project instructions here (prefer edits in \`AGENTS.md\`).
70
+
71
+ `;
72
+ fs.writeFileSync(agentsFile, content, "utf8");
73
+ }
74
+
75
+ // 仅在不存在时创建 CLAUDE.md;存在时保留用户文件类型(普通文件或 symlink)
76
+ const claudeStat = this.safeLstat(claudeFile);
77
+ if (!claudeStat) {
78
+ fs.writeFileSync(claudeFile, "AGENTS.md\n", "utf8");
79
+ }
80
+ }
81
+
82
+ /**
83
+ * 初始化核心 .ufoo 目录
84
+ */
85
+ initCore(project) {
86
+ console.log("[core] Initializing .ufoo core...");
87
+
88
+ const ufooDir = path.join(project, ".ufoo");
89
+ if (!fs.existsSync(ufooDir)) {
90
+ fs.mkdirSync(ufooDir, { recursive: true });
91
+ }
92
+
93
+ // 创建 docs 符号链接
94
+ const docsLink = path.join(ufooDir, "docs");
95
+ const docsTarget = path.join(this.repoRoot, "docs");
96
+
97
+ if (fs.existsSync(docsTarget)) {
98
+ if (fs.existsSync(docsLink)) {
99
+ fs.unlinkSync(docsLink);
100
+ }
101
+ fs.symlinkSync(docsTarget, docsLink);
102
+ console.log(`[core] Created docs symlink: .ufoo/docs -> ${docsTarget}`);
103
+ }
104
+
105
+ console.log("[core] Done");
106
+ }
107
+
108
+ /**
109
+ * 注入 ufoo 模板到 AGENTS.md
110
+ */
111
+ injectAgentsTemplate(project) {
112
+ if (!fs.existsSync(this.agentsTemplate)) {
113
+ console.log("[template] AGENTS.template.md not found, skipping");
114
+ return;
115
+ }
116
+
117
+ const template = fs.readFileSync(this.agentsTemplate, "utf8");
118
+ const targets = this.resolveTemplateTargets(project);
119
+ if (targets.length === 0) {
120
+ console.log("[template] No target markdown files found, skipping");
121
+ return;
122
+ }
123
+
124
+ const labels = targets.map((file) => path.relative(project, file) || path.basename(file));
125
+ console.log(`[template] Injecting ufoo template into: ${labels.join(", ")}`);
126
+
127
+ for (const file of targets) {
128
+ this.injectTemplateIntoFile(file, template);
129
+ }
130
+
131
+ console.log("[template] Done");
132
+ }
133
+
134
+ safeLstat(filePath) {
135
+ try {
136
+ return fs.lstatSync(filePath);
137
+ } catch {
138
+ return null;
139
+ }
140
+ }
141
+
142
+ resolveTemplateTargets(project) {
143
+ const agentsFile = path.resolve(path.join(project, "AGENTS.md"));
144
+ const claudeFile = path.resolve(path.join(project, "CLAUDE.md"));
145
+ const targets = new Set();
146
+
147
+ if (fs.existsSync(agentsFile)) {
148
+ targets.add(agentsFile);
149
+ }
150
+
151
+ const claudeStat = this.safeLstat(claudeFile);
152
+ if (!claudeStat) return Array.from(targets);
153
+
154
+ if (claudeStat.isSymbolicLink()) {
155
+ try {
156
+ const rawTarget = fs.readlinkSync(claudeFile);
157
+ const sourceFile = path.resolve(path.dirname(claudeFile), rawTarget);
158
+ const projectRoot = path.resolve(project);
159
+ const inProject =
160
+ sourceFile === projectRoot ||
161
+ sourceFile.startsWith(`${projectRoot}${path.sep}`);
162
+ if (inProject) {
163
+ targets.add(sourceFile);
164
+ } else {
165
+ console.warn(`[template] CLAUDE.md symlink target outside project, skipped: ${sourceFile}`);
166
+ }
167
+ } catch {
168
+ // ignore broken symlink
169
+ }
170
+ return Array.from(targets);
171
+ }
172
+
173
+ // CLAUDE.md 为独立文件时,双文件都注入模板
174
+ targets.add(claudeFile);
175
+ return Array.from(targets);
176
+ }
177
+
178
+ injectTemplateIntoFile(filePath, template) {
179
+ if (!fs.existsSync(filePath)) return;
180
+
181
+ let content = fs.readFileSync(filePath, "utf8");
182
+ const marker = "<!-- ufoo-template -->";
183
+ if (content.includes(marker)) {
184
+ const startIdx = content.indexOf(marker);
185
+ const endIdx = content.indexOf(marker, startIdx + marker.length);
186
+ if (endIdx !== -1) {
187
+ content =
188
+ content.slice(0, startIdx) +
189
+ `${marker}\n${template}\n${marker}` +
190
+ content.slice(endIdx + marker.length);
191
+ } else {
192
+ content += `\n${marker}\n${template}\n${marker}\n`;
193
+ }
194
+ } else {
195
+ content += `\n${marker}\n${template}\n${marker}\n`;
196
+ }
197
+ fs.writeFileSync(filePath, content, "utf8");
198
+ }
199
+
200
+ /**
201
+ * 初始化 context 模块
202
+ */
203
+ initContext(project) {
204
+ console.log("[context] Initializing decision-only context...");
205
+
206
+ const targetDir = path.join(project, ".ufoo", "context");
207
+ const decisionsDir = path.join(targetDir, "decisions");
208
+ const legacyDir = path.join(targetDir, "DECISIONS");
209
+ const indexFile = path.join(targetDir, "decisions.jsonl");
210
+
211
+ if (!fs.existsSync(targetDir)) {
212
+ fs.mkdirSync(targetDir, { recursive: true });
213
+ }
214
+ if (!fs.existsSync(decisionsDir) && fs.existsSync(legacyDir)) {
215
+ fs.renameSync(legacyDir, decisionsDir);
216
+ }
217
+ if (!fs.existsSync(decisionsDir)) {
218
+ fs.mkdirSync(decisionsDir, { recursive: true });
219
+ }
220
+ if (!fs.existsSync(indexFile)) {
221
+ fs.writeFileSync(indexFile, "", "utf8");
222
+ }
223
+
224
+ console.log("[context] Done");
225
+ }
226
+
227
+ /**
228
+ * 初始化 bus 模块
229
+ */
230
+ async initBus(project) {
231
+ console.log("[bus] Initializing bus module...");
232
+
233
+ const EventBus = require("../bus");
234
+ const bus = new EventBus(project);
235
+
236
+ try {
237
+ await bus.init();
238
+ console.log("[bus] Done");
239
+ } catch (err) {
240
+ console.error(`[bus] Error: ${err.message}`);
241
+ }
242
+ }
243
+
244
+ /**
245
+ * 初始化 resources 模块
246
+ */
247
+ initResources(project) {
248
+ if (!fs.existsSync(this.resourcesMod)) {
249
+ console.log("[resources] Module not found, skipping");
250
+ return;
251
+ }
252
+
253
+ console.log("[resources] Initializing resources module...");
254
+
255
+ const targetDir = path.join(project, ".ufoo", "resources");
256
+
257
+ // 复制模块内容
258
+ this.copyModuleContent(this.resourcesMod, targetDir);
259
+
260
+ console.log("[resources] Done");
261
+ }
262
+
263
+ /**
264
+ * 复制模块内容
265
+ */
266
+ copyModuleContent(src, dest) {
267
+ if (!fs.existsSync(dest)) {
268
+ fs.mkdirSync(dest, { recursive: true });
269
+ }
270
+
271
+ // 复制所有文件和目录(排除 .git、node_modules 等)
272
+ const entries = fs.readdirSync(src, { withFileTypes: true });
273
+
274
+ for (const entry of entries) {
275
+ // 跳过特殊目录
276
+ if (entry.name.startsWith(".") || entry.name === "node_modules") {
277
+ continue;
278
+ }
279
+
280
+ const srcPath = path.join(src, entry.name);
281
+ const destPath = path.join(dest, entry.name);
282
+
283
+ if (entry.isDirectory()) {
284
+ this.copyRecursive(srcPath, destPath);
285
+ } else {
286
+ fs.copyFileSync(srcPath, destPath);
287
+ }
288
+ }
289
+ }
290
+
291
+ /**
292
+ * 递归复制目录
293
+ */
294
+ copyRecursive(src, dest) {
295
+ if (!fs.existsSync(dest)) {
296
+ fs.mkdirSync(dest, { recursive: true });
297
+ }
298
+
299
+ const entries = fs.readdirSync(src, { withFileTypes: true });
300
+
301
+ for (const entry of entries) {
302
+ if (entry.name.startsWith(".") || entry.name === "node_modules") {
303
+ continue;
304
+ }
305
+
306
+ const srcPath = path.join(src, entry.name);
307
+ const destPath = path.join(dest, entry.name);
308
+
309
+ if (entry.isDirectory()) {
310
+ this.copyRecursive(srcPath, destPath);
311
+ } else {
312
+ fs.copyFileSync(srcPath, destPath);
313
+ }
314
+ }
315
+ }
316
+ }
317
+
318
+ module.exports = UfooInit;