u-foo 1.2.11 → 1.2.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "u-foo",
3
- "version": "1.2.11",
3
+ "version": "1.2.12",
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",
@@ -1,6 +1,6 @@
1
1
  const fs = require("fs");
2
2
  const path = require("path");
3
- const { loadConfig } = require("../config");
3
+ const { loadGlobalUcodeConfig } = require("../config");
4
4
 
5
5
  function readJson(filePath = "", fallback = {}) {
6
6
  if (!filePath) return fallback;
@@ -58,10 +58,10 @@ function resolveRuntimeValues({
58
58
  function inspectUcodeRuntimeConfig({
59
59
  projectRoot = process.cwd(),
60
60
  env = process.env,
61
- loadConfigImpl = loadConfig,
61
+ loadConfigImpl = loadGlobalUcodeConfig,
62
62
  } = {}) {
63
63
  const root = path.resolve(projectRoot);
64
- const config = loadConfigImpl(root);
64
+ const config = loadConfigImpl();
65
65
  const resolved = resolveRuntimeValues({
66
66
  env,
67
67
  config,
@@ -84,7 +84,7 @@ function inspectUcodeRuntimeConfig({
84
84
  function prepareUcodeRuntimeConfig({
85
85
  projectRoot = process.cwd(),
86
86
  env = process.env,
87
- loadConfigImpl = loadConfig,
87
+ loadConfigImpl = loadGlobalUcodeConfig,
88
88
  } = {}) {
89
89
  const inspection = inspectUcodeRuntimeConfig({
90
90
  projectRoot,
@@ -2,7 +2,7 @@ const path = require("path");
2
2
  const EventBus = require("../bus");
3
3
  const { IPC_REQUEST_TYPES } = require("../shared/eventContract");
4
4
  const UfooInit = require("../init");
5
- const { loadConfig: loadProjectConfig, saveConfig: saveProjectConfig } = require("../config");
5
+ const { loadConfig: loadProjectConfig, saveConfig: saveProjectConfig, loadGlobalUcodeConfig, saveGlobalUcodeConfig } = require("../config");
6
6
  const { resolveTransport } = require("../code/nativeRunner");
7
7
  const { parseIntervalMs, formatIntervalMs } = require("./cronScheduler");
8
8
 
@@ -64,6 +64,8 @@ function createCommandExecutor(options = {}) {
64
64
  activateAgent = async () => {},
65
65
  loadConfig = loadProjectConfig,
66
66
  saveConfig = saveProjectConfig,
67
+ loadUcodeConfig = loadGlobalUcodeConfig,
68
+ saveUcodeConfig = saveGlobalUcodeConfig,
67
69
  createCronTask = () => null,
68
70
  listCronTasks = () => [],
69
71
  stopCronTask = () => false,
@@ -558,7 +560,7 @@ function createCommandExecutor(options = {}) {
558
560
  const action = (!first || hasInlineKv) ? "set" : first;
559
561
 
560
562
  if (action === "show" || action === "status") {
561
- const config = loadConfig(projectRoot) || {};
563
+ const config = loadUcodeConfig() || {};
562
564
  const provider = String(config.ucodeProvider || "").trim();
563
565
  const model = String(config.ucodeModel || "").trim();
564
566
  const url = String(config.ucodeBaseUrl || "").trim();
@@ -592,8 +594,8 @@ function createCommandExecutor(options = {}) {
592
594
  logMessage("error", "{white-fg}✗{/white-fg} Usage: /settings ucode set provider=<openai|anthropic> model=<id> url=<baseUrl> key=<apiKey>");
593
595
  return;
594
596
  }
595
- saveConfig(projectRoot, updates);
596
- logMessage("system", "{white-fg}✓{/white-fg} ucode config updated");
597
+ saveUcodeConfig(updates);
598
+ logMessage("system", "{white-fg}✓{/white-fg} ucode config updated (global)");
597
599
  if (Object.prototype.hasOwnProperty.call(updates, "ucodeProvider")) {
598
600
  logMessage("system", ` • provider: ${updates.ucodeProvider || "(unset)"}`);
599
601
  }
@@ -606,7 +608,7 @@ function createCommandExecutor(options = {}) {
606
608
  if (Object.prototype.hasOwnProperty.call(updates, "ucodeApiKey")) {
607
609
  logMessage("system", ` • key: ${maskSecret(updates.ucodeApiKey)}`);
608
610
  }
609
- const nextConfig = loadConfig(projectRoot) || {};
611
+ const nextConfig = loadUcodeConfig() || {};
610
612
  logMessage("system", ` • transport: ${inferUcodeTransport(nextConfig.ucodeProvider, nextConfig.ucodeBaseUrl)} (auto)`);
611
613
  return;
612
614
  }
@@ -624,8 +626,8 @@ function createCommandExecutor(options = {}) {
624
626
  logMessage("error", "{white-fg}✗{/white-fg} Usage: /settings ucode clear [provider|model|url|key|all]");
625
627
  return;
626
628
  }
627
- saveConfig(projectRoot, updates);
628
- logMessage("system", "{white-fg}✓{/white-fg} ucode config cleared");
629
+ saveUcodeConfig(updates);
630
+ logMessage("system", "{white-fg}✓{/white-fg} ucode config cleared (global)");
629
631
  return;
630
632
  }
631
633
 
package/src/config.js CHANGED
@@ -2,6 +2,8 @@ const fs = require("fs");
2
2
  const os = require("os");
3
3
  const path = require("path");
4
4
 
5
+ const UCODE_FIELDS = ["ucodeProvider", "ucodeModel", "ucodeBaseUrl", "ucodeApiKey", "ucodeAgentDir"];
6
+
5
7
  const DEFAULT_CONFIG = {
6
8
  launchMode: "auto",
7
9
  agentProvider: "codex-cli",
@@ -9,12 +11,15 @@ const DEFAULT_CONFIG = {
9
11
  assistantEngine: "auto",
10
12
  assistantModel: "",
11
13
  assistantUfooCmd: "",
14
+ autoResume: false,
15
+ };
16
+
17
+ const DEFAULT_UCODE_CONFIG = {
12
18
  ucodeProvider: "",
13
19
  ucodeModel: "",
14
20
  ucodeBaseUrl: "",
15
21
  ucodeApiKey: "",
16
22
  ucodeAgentDir: "",
17
- autoResume: false,
18
23
  };
19
24
 
20
25
  function normalizeLaunchMode(value) {
@@ -58,9 +63,7 @@ function loadJsonSafe(filePath) {
58
63
 
59
64
  function loadConfig(projectRoot) {
60
65
  try {
61
- const globalRaw = loadJsonSafe(globalConfigPath());
62
- const projectRaw = loadJsonSafe(configPath(projectRoot));
63
- const raw = { ...globalRaw, ...projectRaw };
66
+ const raw = loadJsonSafe(configPath(projectRoot));
64
67
  return {
65
68
  ...DEFAULT_CONFIG,
66
69
  ...raw,
@@ -69,15 +72,12 @@ function loadConfig(projectRoot) {
69
72
  assistantEngine: normalizeAssistantEngine(raw.assistantEngine),
70
73
  assistantModel: typeof raw.assistantModel === "string" ? raw.assistantModel : "",
71
74
  assistantUfooCmd: typeof raw.assistantUfooCmd === "string" ? raw.assistantUfooCmd : "",
72
- ucodeProvider: typeof raw.ucodeProvider === "string" ? raw.ucodeProvider : "",
73
- ucodeModel: typeof raw.ucodeModel === "string" ? raw.ucodeModel : "",
74
- ucodeBaseUrl: typeof raw.ucodeBaseUrl === "string" ? raw.ucodeBaseUrl : "",
75
- ucodeApiKey: typeof raw.ucodeApiKey === "string" ? raw.ucodeApiKey : "",
76
- ucodeAgentDir: typeof raw.ucodeAgentDir === "string" ? raw.ucodeAgentDir : "",
77
75
  autoResume: raw.autoResume !== false,
76
+ // Merge ucode fields from global config so callers still see them
77
+ ...loadGlobalUcodeConfig(),
78
78
  };
79
79
  } catch {
80
- return { ...DEFAULT_CONFIG };
80
+ return { ...DEFAULT_CONFIG, ...DEFAULT_UCODE_CONFIG };
81
81
  }
82
82
  }
83
83
 
@@ -90,29 +90,62 @@ function saveConfig(projectRoot, config) {
90
90
  } catch {
91
91
  existing = {};
92
92
  }
93
+ // Strip ucode fields — they belong in global config only
94
+ const projectUpdates = {};
95
+ for (const [k, v] of Object.entries(config)) {
96
+ if (!UCODE_FIELDS.includes(k)) {
97
+ projectUpdates[k] = v;
98
+ }
99
+ }
93
100
  const merged = {
94
101
  ...DEFAULT_CONFIG,
95
102
  ...existing,
96
- ...config,
103
+ ...projectUpdates,
97
104
  };
105
+ // Remove any stale ucode fields from project config
106
+ for (const f of UCODE_FIELDS) {
107
+ delete merged[f];
108
+ }
98
109
  merged.launchMode = normalizeLaunchMode(merged.launchMode);
99
110
  merged.agentProvider = normalizeAgentProvider(merged.agentProvider);
100
111
  merged.assistantEngine = normalizeAssistantEngine(merged.assistantEngine);
101
112
  merged.assistantModel = typeof merged.assistantModel === "string" ? merged.assistantModel : "";
102
113
  merged.assistantUfooCmd = typeof merged.assistantUfooCmd === "string" ? merged.assistantUfooCmd : "";
103
- merged.ucodeProvider = typeof merged.ucodeProvider === "string" ? merged.ucodeProvider : "";
104
- merged.ucodeModel = typeof merged.ucodeModel === "string" ? merged.ucodeModel : "";
105
- merged.ucodeBaseUrl = typeof merged.ucodeBaseUrl === "string" ? merged.ucodeBaseUrl : "";
106
- merged.ucodeApiKey = typeof merged.ucodeApiKey === "string" ? merged.ucodeApiKey : "";
107
- merged.ucodeAgentDir = typeof merged.ucodeAgentDir === "string" ? merged.ucodeAgentDir : "";
108
114
  merged.autoResume = merged.autoResume !== false;
109
115
  fs.writeFileSync(target, JSON.stringify(merged, null, 2));
110
116
  return merged;
111
117
  }
112
118
 
119
+ function loadGlobalUcodeConfig() {
120
+ const raw = loadJsonSafe(globalConfigPath());
121
+ return {
122
+ ucodeProvider: typeof raw.ucodeProvider === "string" ? raw.ucodeProvider : "",
123
+ ucodeModel: typeof raw.ucodeModel === "string" ? raw.ucodeModel : "",
124
+ ucodeBaseUrl: typeof raw.ucodeBaseUrl === "string" ? raw.ucodeBaseUrl : "",
125
+ ucodeApiKey: typeof raw.ucodeApiKey === "string" ? raw.ucodeApiKey : "",
126
+ ucodeAgentDir: typeof raw.ucodeAgentDir === "string" ? raw.ucodeAgentDir : "",
127
+ };
128
+ }
129
+
130
+ function saveGlobalUcodeConfig(updates = {}) {
131
+ const target = globalConfigPath();
132
+ fs.mkdirSync(path.dirname(target), { recursive: true });
133
+ const existing = loadJsonSafe(target);
134
+ const merged = { ...existing };
135
+ for (const [k, v] of Object.entries(updates)) {
136
+ if (UCODE_FIELDS.includes(k)) {
137
+ merged[k] = typeof v === "string" ? v : "";
138
+ }
139
+ }
140
+ fs.writeFileSync(target, JSON.stringify(merged, null, 2));
141
+ return merged;
142
+ }
143
+
113
144
  module.exports = {
114
145
  loadConfig,
115
146
  saveConfig,
147
+ loadGlobalUcodeConfig,
148
+ saveGlobalUcodeConfig,
116
149
  normalizeLaunchMode,
117
150
  normalizeAgentProvider,
118
151
  normalizeAssistantEngine,