u-foo 3.0.19 → 3.0.21

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/bin/ufoo.js CHANGED
@@ -21,7 +21,7 @@ function printMcpHelp() {
21
21
  console.log("Options:");
22
22
  console.log(" --no-auto-start Do not auto-start the home-scoped global controller daemon");
23
23
  console.log(" --json Print status or restart results as JSON");
24
- console.log(" --dry-run Print a Codex HTTP configuration without writing it");
24
+ console.log(" --dry-run Print a sanitized Codex migration preview without writing it");
25
25
  console.log(" -h, --help Display help for the MCP bridge command");
26
26
  console.log("");
27
27
  console.log("Notes:");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "u-foo",
3
- "version": "3.0.19",
3
+ "version": "3.0.21",
4
4
  "description": "Multi-Agent Workspace Protocol. Just add u. claude → uclaude, codex → ucodex.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://ufoo.dev",
@@ -13,6 +13,13 @@ const {
13
13
 
14
14
  const MANAGED_BLOCK_START = "# >>> ufoo MCP (managed)";
15
15
  const MANAGED_BLOCK_END = "# <<< ufoo MCP (managed)";
16
+ const RETIRED_UFOO_SKILL_NAMES = new Set([
17
+ "ubus",
18
+ "uctx",
19
+ "uinit",
20
+ "ustatus",
21
+ "ufoo-poll",
22
+ ]);
16
23
 
17
24
  function tomlString(value = "") {
18
25
  return JSON.stringify(String(value || ""));
@@ -83,10 +90,45 @@ function removeLegacyUfooTransportSections(text = "") {
83
90
  return next;
84
91
  }
85
92
 
93
+ function removeRetiredUfooSkillConfigBlocks(text = "") {
94
+ const source = String(text || "");
95
+ const tables = [];
96
+ const tablePattern = /^\s*(\[{1,2}[^\]\r\n]+\]{1,2})\s*(?:#.*)?$/gm;
97
+ let match;
98
+ while ((match = tablePattern.exec(source)) !== null) {
99
+ tables.push({
100
+ header: match[1],
101
+ start: match.index,
102
+ });
103
+ }
104
+ const ranges = [];
105
+ for (let index = 0; index < tables.length; index += 1) {
106
+ if (tables[index].header !== "[[skills.config]]") continue;
107
+ const start = tables[index].start;
108
+ const end = index + 1 < tables.length ? tables[index + 1].start : source.length;
109
+ const block = source.slice(start, end);
110
+ const pathMatch = block.match(/^\s*path\s*=\s*["']([^"']+)["']\s*(?:#.*)?$/m);
111
+ if (!pathMatch) continue;
112
+ const normalizedPath = pathMatch[1].replace(/\\/g, "/");
113
+ const skillMatch = normalizedPath.match(
114
+ /\/u-foo\/(?:modules\/[^/]+\/)?SKILLS\/([^/]+)\/SKILL\.md$/
115
+ );
116
+ if (skillMatch && RETIRED_UFOO_SKILL_NAMES.has(skillMatch[1])) {
117
+ ranges.push([start, end]);
118
+ }
119
+ }
120
+ let next = source;
121
+ for (const [start, end] of ranges.sort((a, b) => b[0] - a[0])) {
122
+ next = `${next.slice(0, start)}${next.slice(end)}`;
123
+ }
124
+ return next;
125
+ }
126
+
86
127
  function renderCodexConfig(existing, connection) {
87
128
  const withoutManaged = removeManagedBlock(existing);
88
129
  const withoutLegacy = removeLegacyUfooTransportSections(withoutManaged);
89
- const trimmed = withoutLegacy.trimEnd();
130
+ const withoutRetiredSkills = removeRetiredUfooSkillConfigBlocks(withoutLegacy);
131
+ const trimmed = withoutRetiredSkills.trimEnd();
90
132
  return `${trimmed ? `${trimmed}\n\n` : ""}${buildCodexManagedBlock(connection)}\n`;
91
133
  }
92
134
 
@@ -97,7 +139,7 @@ function configureCodexMcp(options = {}) {
97
139
  const existing = fs.existsSync(target) ? fs.readFileSync(target, "utf8") : "";
98
140
  const next = renderCodexConfig(existing, connection);
99
141
  if (options.dryRun === true) {
100
- const redacted = renderCodexConfig(existing, {
142
+ const managedBlock = buildCodexManagedBlock({
101
143
  ...connection,
102
144
  token: "<redacted>",
103
145
  });
@@ -108,7 +150,7 @@ function configureCodexMcp(options = {}) {
108
150
  transport: "streamable_http",
109
151
  endpoint: connection.endpoint,
110
152
  changed: next !== existing,
111
- content: redacted,
153
+ managed_block: managedBlock,
112
154
  };
113
155
  }
114
156
 
@@ -151,7 +193,10 @@ function runMcpConfigureCli(host, options = {}) {
151
193
  }
152
194
  const result = configureCodexMcp(options);
153
195
  if (options.dryRun === true) {
154
- process.stdout.write(result.content);
196
+ process.stdout.write(`Target: ${result.target}\n`);
197
+ process.stdout.write(`Changed: ${result.changed ? "yes" : "no"}\n`);
198
+ process.stdout.write(`Transport: Streamable HTTP ${result.endpoint}\n\n`);
199
+ process.stdout.write(`${result.managed_block}\n`);
155
200
  } else {
156
201
  process.stdout.write(`Configured Codex MCP at ${result.target}\n`);
157
202
  process.stdout.write(`Transport: Streamable HTTP ${result.endpoint}\n`);
@@ -170,6 +215,7 @@ module.exports = {
170
215
  findTomlSections,
171
216
  removeLegacyUfooTransportSections,
172
217
  removeManagedBlock,
218
+ removeRetiredUfooSkillConfigBlocks,
173
219
  renderCodexConfig,
174
220
  runMcpConfigureCli,
175
221
  };