u-foo 2.3.32 → 2.4.0

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 (235) hide show
  1. package/README.md +157 -213
  2. package/README.zh-CN.md +151 -197
  3. package/SKILLS/ufoo/SKILL.md +8 -8
  4. package/bin/uagy.js +69 -0
  5. package/bin/uclaude.js +2 -2
  6. package/bin/ucode.js +4 -4
  7. package/bin/ucodex.js +2 -2
  8. package/bin/ufoo.js +5 -23
  9. package/modules/AGENTS.template.md +1 -1
  10. package/modules/bus/SKILLS/ubus/SKILL.md +35 -10
  11. package/package.json +5 -5
  12. package/scripts/chat-app-smoke.js +1 -1
  13. package/scripts/global-chat-switch-benchmark.js +5 -5
  14. package/scripts/ink-demo.js +1 -1
  15. package/scripts/ink-smoke.js +1 -1
  16. package/scripts/ucode-app-smoke.js +1 -1
  17. package/src/{agent → agents/activity}/activityDetector.js +39 -2
  18. package/src/{agent → agents/activity}/activityStatePublisher.js +1 -1
  19. package/src/{agent → agents/activity}/activityStateWriter.js +2 -2
  20. package/src/{agent → agents/activity}/activityTracker.js +1 -1
  21. package/src/agents/activity/index.js +8 -0
  22. package/src/{agent → agents/controller}/controllerToolExecutor.js +4 -4
  23. package/src/agents/controller/index.js +8 -0
  24. package/src/{agent → agents/controller}/loopObservability.js +2 -2
  25. package/src/{agent → agents/controller}/loopRuntime.js +1 -1
  26. package/src/{agent → agents/controller}/ufooAgent.js +9 -9
  27. package/src/agents/index.js +10 -0
  28. package/src/agents/internal/index.js +3 -0
  29. package/src/{agent → agents/internal}/internalRunner.js +45 -22
  30. package/src/agents/launch/agyConversation.js +159 -0
  31. package/src/agents/launch/index.js +12 -0
  32. package/src/{agent → agents/launch}/launchEnvironment.js +2 -3
  33. package/src/{agent → agents/launch}/launcher.js +64 -21
  34. package/src/{agent → agents/launch}/notifier.js +23 -12
  35. package/src/{agent → agents/launch}/ptyRunner.js +44 -12
  36. package/src/{agent → agents/launch}/ptyWrapper.js +2 -2
  37. package/src/{agent → agents/launch}/publisherRouting.js +1 -1
  38. package/src/{agent → agents/launch}/readyDetector.js +23 -0
  39. package/src/{agent → agents/prompts}/defaultBootstrap.js +63 -4
  40. package/src/{group/bootstrap.js → agents/prompts/groupBootstrap.js} +41 -6
  41. package/src/agents/prompts/index.js +8 -0
  42. package/src/{code/prompts → agents/prompts/native}/index.js +1 -1
  43. package/src/{agent → agents/providers}/claudeThreadProvider.js +1 -1
  44. package/src/{agent → agents/providers}/codexThreadProvider.js +1 -1
  45. package/src/{agent → agents/providers}/directAuthStatus.js +184 -1
  46. package/src/agents/providers/index.js +13 -0
  47. package/src/{agent → agents/providers}/upstreamTransport.js +2 -2
  48. package/src/{chat → app/chat}/agentSockets.js +1 -1
  49. package/src/{chat → app/chat}/commandExecutor.js +50 -26
  50. package/src/{chat → app/chat}/commands.js +119 -5
  51. package/src/{chat → app/chat}/daemonConnection.js +1 -1
  52. package/src/{chat → app/chat}/daemonMessageRouter.js +45 -3
  53. package/src/{chat → app/chat}/dashboardView.js +2 -1
  54. package/src/app/chat/index.js +6 -0
  55. package/src/{chat → app/chat}/inputSubmitHandler.js +4 -13
  56. package/src/{chat → app/chat}/internalAgentLogHistory.js +1 -1
  57. package/src/app/chat/multiWindow/index.js +268 -0
  58. package/src/app/chat/multiWindow/paneLayout.js +84 -0
  59. package/src/app/chat/multiWindow/paneManager.js +299 -0
  60. package/src/app/chat/multiWindow/renderer.js +384 -0
  61. package/src/app/chat/multiWindow/virtualTerminal.js +327 -0
  62. package/src/{chat → app/chat}/transport.js +1 -1
  63. package/src/{cli → app/cli}/ctxCoreCommands.js +3 -3
  64. package/src/{doctor/index.js → app/cli/features/doctor.js} +1 -1
  65. package/src/{init/index.js → app/cli/features/init.js} +14 -32
  66. package/src/{cli → app/cli}/groupCoreCommands.js +2 -2
  67. package/src/app/cli/index.js +9 -0
  68. package/src/{cli → app/cli}/onlineCoreCommands.js +5 -5
  69. package/src/{cli.js → app/cli/run.js} +59 -57
  70. package/src/app/index.js +6 -0
  71. package/src/code/agent.js +10 -9
  72. package/src/code/index.js +2 -0
  73. package/src/code/launcher/index.js +9 -0
  74. package/src/{agent → code/launcher}/ucode.js +7 -8
  75. package/src/{agent → code/launcher}/ucodeBootstrap.js +3 -3
  76. package/src/{agent → code/launcher}/ucodeBuild.js +2 -2
  77. package/src/{agent → code/launcher}/ucodeDoctor.js +2 -2
  78. package/src/{agent → code/launcher}/ucodeRuntimeConfig.js +1 -2
  79. package/src/code/nativeRunner.js +4 -4
  80. package/src/code/tui.js +3 -1454
  81. package/src/config.js +15 -2
  82. package/src/{bus → coordination/bus}/activate.js +2 -2
  83. package/src/{bus → coordination/bus}/daemon.js +15 -5
  84. package/src/coordination/bus/envelope.js +173 -0
  85. package/src/{bus → coordination/bus}/index.js +7 -3
  86. package/src/{bus → coordination/bus}/inject.js +11 -3
  87. package/src/{bus → coordination/bus}/message.js +1 -1
  88. package/src/coordination/bus/messageMeta.js +130 -0
  89. package/src/coordination/bus/promptEnvelope.js +65 -0
  90. package/src/{bus → coordination/bus}/shake.js +1 -1
  91. package/src/{bus → coordination/bus}/store.js +3 -3
  92. package/src/{bus → coordination/bus}/subscriber.js +2 -2
  93. package/src/{bus → coordination/bus}/utils.js +2 -2
  94. package/src/{history → coordination/history}/inputTimeline.js +5 -5
  95. package/src/coordination/index.js +10 -0
  96. package/src/{memory → coordination/memory}/historySearch.js +1 -1
  97. package/src/{memory → coordination/memory}/index.js +3 -3
  98. package/src/{report → coordination/report}/store.js +2 -2
  99. package/src/{status → coordination/status}/index.js +3 -3
  100. package/src/online/bridge.js +2 -2
  101. package/src/{controller → orchestration/controller}/flags.js +1 -1
  102. package/src/{controller → orchestration/controller}/gateRouter.js +1 -1
  103. package/src/orchestration/controller/index.js +10 -0
  104. package/src/{controller → orchestration/controller}/shadowGuard.js +1 -1
  105. package/src/orchestration/groups/bootstrap.js +3 -0
  106. package/src/orchestration/groups/index.js +10 -0
  107. package/src/orchestration/groups/promptProfiles.js +3 -0
  108. package/src/{group → orchestration/groups}/templates.js +1 -1
  109. package/src/{group → orchestration/groups}/validateTemplate.js +1 -1
  110. package/src/orchestration/index.js +7 -0
  111. package/src/orchestration/solo/index.js +3 -0
  112. package/src/{daemon → runtime/daemon}/agentProcessManager.js +1 -1
  113. package/src/{daemon → runtime/daemon}/cronOps.js +3 -2
  114. package/src/{daemon → runtime/daemon}/groupOrchestrator.js +26 -9
  115. package/src/{daemon → runtime/daemon}/index.js +105 -53
  116. package/src/{daemon → runtime/daemon}/ipcServer.js +1 -1
  117. package/src/{daemon → runtime/daemon}/nicknameScope.js +6 -3
  118. package/src/{daemon → runtime/daemon}/ops.js +48 -61
  119. package/src/{daemon → runtime/daemon}/promptLoop.js +1 -1
  120. package/src/{daemon → runtime/daemon}/promptRequest.js +7 -7
  121. package/src/runtime/daemon/providerSessions.js +230 -0
  122. package/src/{daemon → runtime/daemon}/reporting.js +4 -4
  123. package/src/{daemon → runtime/daemon}/run.js +4 -4
  124. package/src/{daemon → runtime/daemon}/soloBootstrap.js +7 -7
  125. package/src/{daemon → runtime/daemon}/status.js +5 -5
  126. package/src/runtime/index.js +10 -0
  127. package/src/{projects → runtime/projects}/registry.js +1 -1
  128. package/src/{terminal → runtime/terminal}/adapterRouter.js +0 -10
  129. package/src/{terminal → runtime/terminal}/adapters/internalAdapter.js +0 -4
  130. package/src/tools/handlers/common.js +1 -1
  131. package/src/tools/handlers/listAgents.js +1 -1
  132. package/src/tools/handlers/memory.js +3 -3
  133. package/src/tools/handlers/readBusSummary.js +1 -1
  134. package/src/tools/handlers/readOpenDecisions.js +1 -1
  135. package/src/tools/handlers/readProjectRegistry.js +1 -1
  136. package/src/tools/handlers/readPromptHistory.js +2 -2
  137. package/src/tools/schemaFixtures.js +1 -1
  138. package/src/ui/MIGRATION.md +42 -88
  139. package/src/ui/format/index.js +5 -28
  140. package/src/ui/index.js +1 -1
  141. package/src/ui/{components → ink}/ChatApp.js +812 -88
  142. package/src/ui/ink/DashboardBar.js +685 -0
  143. package/src/ui/{components → ink}/MultilineInput.js +230 -5
  144. package/src/ui/{components → ink}/UcodeApp.js +16 -7
  145. package/src/ui/{components → ink}/agentMirror.js +24 -19
  146. package/src/ui/{components → ink}/chatReducer.js +29 -7
  147. package/src/bus/messageMeta.js +0 -52
  148. package/src/chat/agentViewController.js +0 -1072
  149. package/src/chat/chatLogController.js +0 -138
  150. package/src/chat/completionController.js +0 -533
  151. package/src/chat/dashboardKeyController.js +0 -533
  152. package/src/chat/index.js +0 -2222
  153. package/src/chat/inputHistoryController.js +0 -135
  154. package/src/chat/inputListenerController.js +0 -470
  155. package/src/chat/layout.js +0 -186
  156. package/src/chat/pasteController.js +0 -81
  157. package/src/chat/statusLineController.js +0 -223
  158. package/src/chat/streamTracker.js +0 -156
  159. package/src/code/config +0 -0
  160. package/src/daemon/providerSessions.js +0 -488
  161. package/src/terminal/adapters/internalPtyAdapter.js +0 -42
  162. package/src/ui/components/DashboardBar.js +0 -417
  163. /package/src/{code/prompts → agents/prompts/native}/actions.js +0 -0
  164. /package/src/{code/prompts → agents/prompts/native}/efficiency.js +0 -0
  165. /package/src/{code/prompts → agents/prompts/native}/environment.js +0 -0
  166. /package/src/{code/prompts → agents/prompts/native}/identity.js +0 -0
  167. /package/src/{code/prompts → agents/prompts/native}/safety.js +0 -0
  168. /package/src/{code/prompts → agents/prompts/native}/sections.js +0 -0
  169. /package/src/{code/prompts → agents/prompts/native}/system.js +0 -0
  170. /package/src/{code/prompts → agents/prompts/native}/tasks.js +0 -0
  171. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/bash.js +0 -0
  172. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/edit.js +0 -0
  173. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/read.js +0 -0
  174. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/write.js +0 -0
  175. /package/src/{code/prompts → agents/prompts/native}/ufoo.js +0 -0
  176. /package/src/{group → agents/prompts}/promptProfiles.js +0 -0
  177. /package/src/{agent → agents/providers}/claudeEventTranslator.js +0 -0
  178. /package/src/{agent → agents/providers}/claudeOauthTokenReader.js +0 -0
  179. /package/src/{agent → agents/providers}/claudeSessionFiles.js +0 -0
  180. /package/src/{agent → agents/providers}/codexEventTranslator.js +0 -0
  181. /package/src/{agent → agents/providers}/credentials/claude.js +0 -0
  182. /package/src/{agent → agents/providers}/credentials/codex.js +0 -0
  183. /package/src/{agent → agents/providers}/credentials/index.js +0 -0
  184. /package/src/{chat → app/chat}/agentBar.js +0 -0
  185. /package/src/{chat → app/chat}/agentDirectory.js +0 -0
  186. /package/src/{chat → app/chat}/cronScheduler.js +0 -0
  187. /package/src/{chat → app/chat}/daemonCoordinator.js +0 -0
  188. /package/src/{chat → app/chat}/daemonReconnect.js +0 -0
  189. /package/src/{chat → app/chat}/daemonTransport.js +0 -0
  190. /package/src/{chat → app/chat}/daemonTransportDefaults.js +0 -0
  191. /package/src/{chat → app/chat}/inputMath.js +0 -0
  192. /package/src/{chat → app/chat}/projectCloseController.js +0 -0
  193. /package/src/{chat → app/chat}/rawKeyMap.js +0 -0
  194. /package/src/{chat → app/chat}/settingsController.js +0 -0
  195. /package/src/{chat → app/chat}/shellCommand.js +0 -0
  196. /package/src/{chat → app/chat}/text.js +0 -0
  197. /package/src/{chat → app/chat}/transientAgentState.js +0 -0
  198. /package/src/{cli → app/cli}/busCoreCommands.js +0 -0
  199. /package/src/{skills/index.js → app/cli/features/skills.js} +0 -0
  200. /package/src/{bus → coordination/bus}/nickname.js +0 -0
  201. /package/src/{bus → coordination/bus}/queue.js +0 -0
  202. /package/src/{context → coordination/context}/decisions.js +0 -0
  203. /package/src/{context → coordination/context}/doctor.js +0 -0
  204. /package/src/{context → coordination/context}/index.js +0 -0
  205. /package/src/{context → coordination/context}/sync.js +0 -0
  206. /package/src/{ufoo → coordination/state}/agentRegistryDiagnostics.js +0 -0
  207. /package/src/{ufoo → coordination/state}/agentsStore.js +0 -0
  208. /package/src/{ufoo → coordination/state}/paths.js +0 -0
  209. /package/src/{controller → orchestration/controller}/launchRouting.js +0 -0
  210. /package/src/{controller → orchestration/controller}/routerFastPath.js +0 -0
  211. /package/src/{controller → orchestration/controller}/routerFinalize.js +0 -0
  212. /package/src/{group → orchestration/groups}/diagram.js +0 -0
  213. /package/src/{group → orchestration/groups}/templateValidation.js +0 -0
  214. /package/src/{solo → orchestration/solo}/commands.js +0 -0
  215. /package/src/{shared → runtime/contracts}/eventContract.js +0 -0
  216. /package/src/{shared → runtime/contracts}/ptySocketContract.js +0 -0
  217. /package/src/{providerapi → runtime/privacy}/redactor.js +0 -0
  218. /package/src/{providerapi → runtime/privacy}/shadowDiff.js +0 -0
  219. /package/src/{utils → runtime/process}/nodeExecutable.js +0 -0
  220. /package/src/{projects → runtime/projects}/identity.js +0 -0
  221. /package/src/{projects → runtime/projects}/index.js +0 -0
  222. /package/src/{projects → runtime/projects}/projectId.js +0 -0
  223. /package/src/{projects → runtime/projects}/runtimes.js +0 -0
  224. /package/src/{terminal → runtime/terminal}/adapterContract.js +0 -0
  225. /package/src/{terminal → runtime/terminal}/adapters/externalAdapter.js +0 -0
  226. /package/src/{terminal → runtime/terminal}/adapters/hostAdapter.js +0 -0
  227. /package/src/{terminal → runtime/terminal}/adapters/internalQueueAdapter.js +0 -0
  228. /package/src/{terminal → runtime/terminal}/adapters/terminalAdapter.js +0 -0
  229. /package/src/{terminal → runtime/terminal}/adapters/tmuxAdapter.js +0 -0
  230. /package/src/{terminal → runtime/terminal}/detect.js +0 -0
  231. /package/src/{terminal → runtime/terminal}/index.js +0 -0
  232. /package/src/{terminal → runtime/terminal}/iterm2.js +0 -0
  233. /package/src/{utils → ui/format}/banner.js +0 -0
  234. /package/src/{shared → ui/format}/markdownRenderer.js +0 -0
  235. /package/src/ui/{components → ink}/InkDemo.js +0 -0
@@ -8,9 +8,9 @@ const {
8
8
  getTimestamp,
9
9
  writeFileAtomic,
10
10
  } = require("../bus/utils");
11
- const { redactSecrets } = require("../providerapi/redactor");
12
- const { canonicalProjectRoot } = require("../projects/projectId");
13
- const { getUfooPaths } = require("../ufoo/paths");
11
+ const { redactSecrets } = require("../../runtime/privacy/redactor");
12
+ const { canonicalProjectRoot } = require("../../runtime/projects/projectId");
13
+ const { getUfooPaths } = require("../state/paths");
14
14
 
15
15
  const SCHEMA_VERSION = "1.0";
16
16
  const ID_PREFIX = "mem-";
@@ -1,7 +1,7 @@
1
1
  const fs = require("fs");
2
2
  const path = require("path");
3
- const { getUfooPaths } = require("../ufoo/paths");
4
- const { redactSecrets } = require("../providerapi/redactor");
3
+ const { getUfooPaths } = require("../state/paths");
4
+ const { redactSecrets } = require("../../runtime/privacy/redactor");
5
5
 
6
6
  const REPORT_PHASES = {
7
7
  START: "start",
@@ -2,12 +2,12 @@ const fs = require("fs");
2
2
  const path = require("path");
3
3
  const childProcess = require("child_process");
4
4
  const { readJSON } = require("../bus/utils");
5
- const { getUfooPaths } = require("../ufoo/paths");
6
- const { resolveDisplayNickname } = require("../daemon/nicknameScope");
5
+ const { getUfooPaths } = require("../state/paths");
6
+ const { resolveDisplayNickname } = require("../../runtime/daemon/nicknameScope");
7
7
  const {
8
8
  inspectDirectAuthStatus,
9
9
  formatDirectAuthStatus,
10
- } = require("../agent/directAuthStatus");
10
+ } = require("../../agents/providers/directAuthStatus");
11
11
 
12
12
  function normalizeTty(ttyPath) {
13
13
  if (!ttyPath) return "";
@@ -233,7 +233,7 @@ class OnlineConnect {
233
233
 
234
234
  // Init local bus only when sync is enabled
235
235
  if (this.syncEnabled) {
236
- const EventBus = require("../bus");
236
+ const EventBus = require("../coordination/bus");
237
237
  this.eventBus = new EventBus(this.projectRoot);
238
238
  await this.eventBus.ensureJoined();
239
239
  }
@@ -666,7 +666,7 @@ class OnlineConnect {
666
666
  }
667
667
 
668
668
  try {
669
- const DecisionsManager = require("../context/decisions");
669
+ const DecisionsManager = require("../coordination/context/decisions");
670
670
  const manager = new DecisionsManager(this.projectRoot);
671
671
  manager.writeIndex();
672
672
  } catch {
@@ -1,6 +1,6 @@
1
1
  const fs = require("fs");
2
2
  const path = require("path");
3
- const { loadConfig, normalizeControllerMode } = require("../config");
3
+ const { loadConfig, normalizeControllerMode } = require("../../config");
4
4
 
5
5
  const CONTROLLER_MODES = Object.freeze({
6
6
  LEGACY: "legacy",
@@ -5,7 +5,7 @@ const {
5
5
  defaultRouterProviderForAgentProvider,
6
6
  defaultRouterModelForProvider,
7
7
  sameModelProvider,
8
- } = require("../config");
8
+ } = require("../../config");
9
9
 
10
10
  const DEFAULT_EXECUTION_PATH = "main";
11
11
  const DEFAULT_CONFIDENCE_THRESHOLD = 0.6;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ module.exports = {
4
+ ...require("./flags"),
5
+ ...require("./gateRouter"),
6
+ ...require("./launchRouting"),
7
+ ...require("./routerFastPath"),
8
+ ...require("./routerFinalize"),
9
+ ...require("./shadowGuard"),
10
+ };
@@ -4,7 +4,7 @@ const crypto = require("crypto");
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
6
 
7
- const { getUfooPaths } = require("../ufoo/paths");
7
+ const { getUfooPaths } = require("../../coordination/state/paths");
8
8
 
9
9
  const DEFAULT_SHADOW_SAMPLING_RATE = 0.1;
10
10
  const DEFAULT_SHADOW_DAILY_INPUT_TOKEN_LIMIT = 50000;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+
3
+ module.exports = require("../../agents/prompts/groupBootstrap");
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ module.exports = {
4
+ ...require("./bootstrap"),
5
+ ...require("./diagram"),
6
+ ...require("./promptProfiles"),
7
+ ...require("./templateValidation"),
8
+ ...require("./templates"),
9
+ ...require("./validateTemplate"),
10
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+
3
+ module.exports = require("../../agents/prompts/promptProfiles");
@@ -18,7 +18,7 @@ const SOURCE_PRIORITY = [
18
18
  ];
19
19
 
20
20
  function defaultBuiltinTemplatesDir() {
21
- return path.join(path.resolve(__dirname, "..", ".."), "templates", "groups");
21
+ return path.join(path.resolve(__dirname, "..", "..", ".."), "templates", "groups");
22
22
  }
23
23
 
24
24
  function defaultGlobalTemplatesDir() {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- const ALLOWED_AGENT_TYPES = new Set(["auto", "codex", "claude", "ucode"]);
3
+ const ALLOWED_AGENT_TYPES = new Set(["auto", "codex", "claude", "ucode", "agy"]);
4
4
  const { resolvePromptProfileReference } = require("./promptProfiles");
5
5
 
6
6
  function isPlainObject(value) {
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ module.exports = {
4
+ controller: require("./controller"),
5
+ groups: require("./groups"),
6
+ solo: require("./solo"),
7
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+
3
+ module.exports = require("./commands");
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- const EventBus = require("../bus");
3
+ const EventBus = require("../../coordination/bus");
4
4
 
5
5
  class AgentProcessManager {
6
6
  constructor(projectRoot) {
@@ -1,10 +1,10 @@
1
1
  const fs = require("fs");
2
2
  const path = require("path");
3
- const { getUfooPaths } = require("../ufoo/paths");
3
+ const { getUfooPaths } = require("../../coordination/state/paths");
4
4
  const {
5
5
  parseIntervalMs,
6
6
  formatIntervalMs,
7
- } = require("../chat/cronScheduler");
7
+ } = require("../../app/chat/cronScheduler");
8
8
 
9
9
  function splitTargets(value = "") {
10
10
  return String(value || "")
@@ -342,6 +342,7 @@ function createDaemonCronController(options = {}) {
342
342
  };
343
343
 
344
344
  attachTaskTimer(task);
345
+ runTask(task);
345
346
  tasks.push(task);
346
347
  persistState();
347
348
 
@@ -2,17 +2,17 @@
2
2
 
3
3
  const fs = require("fs");
4
4
  const path = require("path");
5
- const EventBus = require("../bus");
6
- const { prepareUcodeBootstrap } = require("../agent/ucodeBootstrap");
7
- const { loadConfig } = require("../config");
5
+ const EventBus = require("../../coordination/bus");
6
+ const { prepareUcodeBootstrap } = require("../../code/launcher/ucodeBootstrap");
7
+ const { loadConfig } = require("../../config");
8
8
  const {
9
9
  buildGroupPromptMetadata,
10
10
  composeGroupBootstrapPrompt,
11
11
  computeBootstrapFingerprint,
12
12
  computeRosterVersion,
13
- } = require("../group/bootstrap");
14
- const { validateTemplateTarget: validateGroupTemplateTarget } = require("../group/templateValidation");
15
- const { getUfooPaths } = require("../ufoo/paths");
13
+ } = require("../../orchestration/groups/bootstrap");
14
+ const { validateTemplateTarget: validateGroupTemplateTarget } = require("../../orchestration/groups/templateValidation");
15
+ const { getUfooPaths } = require("../../coordination/state/paths");
16
16
  const {
17
17
  normalizeNicknameSegment,
18
18
  buildProjectNicknamePrefix,
@@ -36,12 +36,15 @@ function resolveBootstrapInjectSettleMs(agentType = "", promptText = "", options
36
36
  delayMs = 800;
37
37
  } else if (normalizedAgent === "codex") {
38
38
  delayMs = 250;
39
+ } else if (normalizedAgent === "agy") {
40
+ // Agy uses an ink-style TUI like claude — same input handler latency.
41
+ delayMs = 800;
39
42
  }
40
43
 
41
44
  const text = typeof promptText === "string" ? promptText : "";
42
45
  if (!text) return delayMs;
43
46
  if (text.includes("\n")) {
44
- delayMs += normalizedAgent === "claude" ? 200 : 100;
47
+ delayMs += (normalizedAgent === "claude" || normalizedAgent === "agy") ? 200 : 100;
45
48
  }
46
49
  if (text.length > 1024) {
47
50
  delayMs += Math.min(800, Math.ceil(text.length / 1024) * 120);
@@ -306,6 +309,7 @@ function resolveAutoAgentType(projectRoot, requestedType) {
306
309
  const provider = asTrimmedString(loadConfig(projectRoot).agentProvider);
307
310
  if (provider === "claude-cli") return "claude";
308
311
  if (provider === "ucode") return "ucode";
312
+ if (provider === "agy-cli") return "agy";
309
313
  return "codex";
310
314
  }
311
315
 
@@ -386,7 +390,14 @@ function buildExecutionPlan({
386
390
  ? "ucode-bootstrap-file"
387
391
  : (resolvedType === "claude"
388
392
  ? "system-prompt-file"
389
- : (resolvedType === "codex" ? "initial-prompt-arg" : "post-launch-inject")));
393
+ : (resolvedType === "codex"
394
+ ? "initial-prompt-arg"
395
+ // Agy takes the bootstrap as `-i <text>`, same shape as codex's
396
+ // positional initial prompt — both pass the bootstrap as a flag,
397
+ // not via post-launch injection.
398
+ : (resolvedType === "agy"
399
+ ? "initial-prompt-arg"
400
+ : "post-launch-inject"))));
390
401
  const bootstrapPrompt = bootstrapRequired
391
402
  ? composeGroupBootstrapPrompt({
392
403
  profilePrompt: resolvedProfile.prompt,
@@ -908,12 +919,18 @@ function createGroupOrchestrator(options = {}) {
908
919
  // Codex: pass bootstrap prompt as the initial [PROMPT] CLI argument.
909
920
  // Codex doesn't support --append-system-prompt, but accepts an initial
910
921
  // prompt argument that becomes the first user message at startup.
922
+ //
923
+ // Agy uses the same "send bootstrap as a launch flag" model, but its
924
+ // flag is `-i <text>` (alias for --prompt-interactive). Same strategy
925
+ // key, different arg shape.
911
926
  if (item.bootstrap_strategy === "initial-prompt-arg") {
912
927
  member.bootstrap_attempted_at = nowIso();
913
928
  member.bootstrap_error = "";
914
929
  const promptText = (item.bootstrap_prompt || "").trim();
915
930
  if (promptText) {
916
- extraArgs = [promptText];
931
+ extraArgs = item.type === "agy"
932
+ ? ["-i", promptText]
933
+ : [promptText];
917
934
  bootstrapInjected = true;
918
935
  }
919
936
  }
@@ -2,22 +2,22 @@ const fs = require("fs");
2
2
  const path = require("path");
3
3
  const net = require("net");
4
4
  const { spawn, spawnSync } = require("child_process");
5
- const { runUfooAgent, runUfooRouteAgent } = require("../agent/ufooAgent");
5
+ const { runUfooAgent, runUfooRouteAgent } = require("../../agents/controller/ufooAgent");
6
6
  const { launchAgent, closeAgent, getRecoverableAgents, resumeAgents } = require("./ops");
7
7
  const { buildStatus } = require("./status");
8
- const EventBus = require("../bus");
8
+ const EventBus = require("../../coordination/bus");
9
9
  const { AgentProcessManager } = require("./agentProcessManager");
10
- const NicknameManager = require("../bus/nickname");
11
- const { generateInstanceId, subscriberToSafeName } = require("../bus/utils");
10
+ const NicknameManager = require("../../coordination/bus/nickname");
11
+ const { generateInstanceId, subscriberToSafeName } = require("../../coordination/bus/utils");
12
12
  const { createDaemonIpcServer } = require("./ipcServer");
13
- const { IPC_REQUEST_TYPES, IPC_RESPONSE_TYPES, BUS_STATUS_PHASES } = require("../shared/eventContract");
14
- const { getUfooPaths } = require("../ufoo/paths");
13
+ const { IPC_REQUEST_TYPES, IPC_RESPONSE_TYPES, BUS_STATUS_PHASES } = require("../contracts/eventContract");
14
+ const { getUfooPaths } = require("../../coordination/state/paths");
15
15
  const { upsertProjectRuntime, markProjectStopped } = require("../projects");
16
- const { scheduleProviderSessionProbe, resolveSessionFromFile, persistProviderSession, loadProviderSessionCache } = require("./providerSessions");
16
+ const { scheduleProviderSessionResolve, resolveSessionFromFile, persistProviderSession, loadProviderSessionCache } = require("./providerSessions");
17
17
  const { createTerminalAdapterRouter } = require("../terminal/adapterRouter");
18
18
  const { createDaemonCronController } = require("./cronOps");
19
19
  const { createGroupOrchestrator } = require("./groupOrchestrator");
20
- const { normalizeFormat, renderGroupDiagramFromTemplate, renderGroupDiagramFromRuntime } = require("../group/diagram");
20
+ const { normalizeFormat, renderGroupDiagramFromTemplate, renderGroupDiagramFromRuntime } = require("../../orchestration/groups/diagram");
21
21
  const { runPromptWithAssistant } = require("./promptLoop");
22
22
  const { handlePromptRequest } = require("./promptRequest");
23
23
  const { recordAgentReport } = require("./reporting");
@@ -36,10 +36,10 @@ const {
36
36
  resolveDisplayNickname,
37
37
  resolveScopedNickname,
38
38
  } = require("./nicknameScope");
39
- const { resolveNodeExecutable } = require("../utils/nodeExecutable");
39
+ const { resolveNodeExecutable } = require("../process/nodeExecutable");
40
40
 
41
41
  let providerSessions = null;
42
- let probeHandles = new Map();
42
+ let sessionResolveHandles = new Map();
43
43
  let daemonCronController = null;
44
44
  let daemonGroupOrchestrator = null;
45
45
  const PROJECT_RUNTIME_HEARTBEAT_MS = 10 * 1000;
@@ -53,6 +53,7 @@ function normalizeBusAgentType(agentType = "") {
53
53
  if (!value) return "claude-code";
54
54
  if (value === "codex") return "codex";
55
55
  if (value === "claude" || value === "claude-code") return "claude-code";
56
+ if (value === "agy" || value === "antigravity") return "agy";
56
57
  if (value === "ufoo" || value === "ucode" || value === "ufoo-code") return "ufoo-code";
57
58
  return value;
58
59
  }
@@ -61,6 +62,7 @@ function normalizeLaunchAgent(agent = "") {
61
62
  const value = String(agent || "").trim().toLowerCase();
62
63
  if (value === "codex") return "codex";
63
64
  if (value === "claude" || value === "claude-code") return "claude";
65
+ if (value === "agy" || value === "antigravity") return "agy";
64
66
  if (value === "ufoo" || value === "ucode" || value === "ufoo-code") return "ufoo";
65
67
  return "";
66
68
  }
@@ -218,7 +220,7 @@ function isLikelyDaemonProcess(pid) {
218
220
  const hasCliPattern = /\bufoo\s+daemon\s+(--start|start)\b/.test(text);
219
221
  const hasNodePattern = /\bufoo\.js\s+daemon\s+(--start|start)\b/.test(text);
220
222
  if (hasCliPattern || hasNodePattern) return true;
221
- if (text.includes("/src/daemon/run.js")) return true;
223
+ if (text.includes("/src/runtime/daemon/run.js")) return true;
222
224
  return false;
223
225
  }
224
226
 
@@ -609,17 +611,15 @@ async function handleOps(projectRoot, ops = [], processManager = null) {
609
611
  op.require_activity_monitor === true || op.requireActivityMonitor === true,
610
612
  });
611
613
  if (launchResult.mode === "internal" && launchResult.subscriberIds && launchResult.subscriberIds.length > 0) {
612
- const probeAgentType = agent === "codex"
614
+ const sessionResolveAgentType = agent === "codex"
613
615
  ? "codex"
614
616
  : (agent === "claude" ? "claude-code" : "");
615
617
  for (const subscriberId of launchResult.subscriberIds) {
616
- if (!probeAgentType) continue;
617
- const resolvedNickname = resolveSubscriberNickname(projectRoot, subscriberId) || nickname;
618
- const probeHandle = scheduleProviderSessionProbe({
618
+ if (!sessionResolveAgentType) continue;
619
+ const sessionResolveHandle = scheduleProviderSessionResolve({
619
620
  projectRoot,
620
621
  subscriberId,
621
- agentType: probeAgentType,
622
- nickname: resolvedNickname,
622
+ agentType: sessionResolveAgentType,
623
623
  agentCwd: projectRoot,
624
624
  onResolved: (id, resolved) => {
625
625
  if (providerSessions) {
@@ -629,11 +629,11 @@ async function handleOps(projectRoot, ops = [], processManager = null) {
629
629
  updated_at: new Date().toISOString(),
630
630
  });
631
631
  }
632
- probeHandles.delete(id);
632
+ sessionResolveHandles.delete(id);
633
633
  },
634
634
  });
635
- if (probeHandle) {
636
- probeHandles.set(subscriberId, probeHandle);
635
+ if (sessionResolveHandle) {
636
+ sessionResolveHandles.set(subscriberId, sessionResolveHandle);
637
637
  }
638
638
  }
639
639
  }
@@ -796,21 +796,61 @@ async function dispatchMessages(projectRoot, dispatch = []) {
796
796
  const eventBus = new EventBus(projectRoot);
797
797
  // Always use "ufoo-agent" as the publisher for daemon messages
798
798
  const defaultPublisher = "ufoo-agent";
799
+ const resolveDispatchTarget = (target) => {
800
+ const raw = String(target || "").trim();
801
+ if (!raw || raw === "broadcast") return raw;
802
+ try {
803
+ eventBus.ensureBus();
804
+ eventBus.loadBusData();
805
+ const agents = eventBus.busData && eventBus.busData.agents && typeof eventBus.busData.agents === "object"
806
+ ? eventBus.busData.agents
807
+ : {};
808
+ if (agents[raw]) return raw;
809
+
810
+ const candidates = [raw];
811
+ const scoped = applyProjectNicknamePrefix(projectRoot, raw);
812
+ if (scoped && scoped !== raw) candidates.push(scoped);
813
+
814
+ for (const candidate of candidates) {
815
+ for (const [id, meta] of Object.entries(agents)) {
816
+ if (!meta || meta.status !== "active") continue;
817
+ if (
818
+ meta.nickname === candidate
819
+ || meta.scoped_nickname === candidate
820
+ || meta.display_nickname === candidate
821
+ ) {
822
+ return id;
823
+ }
824
+ }
825
+ }
826
+
827
+ if (eventBus.messageManager && eventBus.messageManager.resolveTarget(raw).length > 0) {
828
+ return raw;
829
+ }
830
+ } catch {
831
+ // Fall through to the original target; send will surface/log the failure below.
832
+ }
833
+ return raw;
834
+ };
799
835
  for (const item of dispatch) {
800
836
  if (!item || !item.target || !item.message) continue;
801
837
  const pub = item.publisher || defaultPublisher;
838
+ const target = resolveDispatchTarget(item.target);
802
839
  const sendOptions = {
803
840
  injectionMode: item.injection_mode,
804
841
  source: item.source,
805
842
  };
806
843
  try {
807
- if (item.target === "broadcast") {
844
+ if (target === "broadcast") {
808
845
  await eventBus.broadcast(item.message, pub, sendOptions);
809
846
  } else {
810
- await eventBus.send(item.target, item.message, pub, sendOptions);
847
+ await eventBus.send(target, item.message, pub, sendOptions);
811
848
  }
812
- } catch {
813
- // ignore dispatch failures
849
+ } catch (err) {
850
+ appendControlLog(
851
+ projectRoot,
852
+ `dispatch failed target=${JSON.stringify(item.target)} resolved=${JSON.stringify(target)} error=${err && err.message ? err.message : String(err)}`
853
+ );
814
854
  }
815
855
  }
816
856
  }
@@ -1218,7 +1258,7 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
1218
1258
 
1219
1259
  // Provider session cache (in-memory)
1220
1260
  providerSessions = loadProviderSessionCache(projectRoot);
1221
- probeHandles = new Map();
1261
+ sessionResolveHandles = new Map();
1222
1262
  daemonCronController = createDaemonCronController({
1223
1263
  projectRoot,
1224
1264
  dispatch: async ({ taskId, target, message }) => {
@@ -1318,13 +1358,13 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
1318
1358
  }
1319
1359
  const targetPaths = getUfooPaths(root);
1320
1360
  if (!fs.existsSync(targetPaths.ufooDir)) {
1321
- const repoRoot = path.join(__dirname, "..", "..");
1322
- const init = new (require("../init"))(repoRoot);
1361
+ const repoRoot = path.join(__dirname, "..", "..", "..");
1362
+ const init = new (require("../../app/cli/features/init"))(repoRoot);
1323
1363
  await init.init({ modules: "context,bus", project: root });
1324
1364
  }
1325
1365
  if (!isRunning(root)) {
1326
1366
  cleanupStaleState(root);
1327
- const daemonBin = path.join(__dirname, "..", "..", "bin", "ufoo.js");
1367
+ const daemonBin = path.join(__dirname, "..", "..", "..", "bin", "ufoo.js");
1328
1368
  const child = spawn(resolveNodeExecutable(), [daemonBin, "daemon", "--start"], {
1329
1369
  detached: true,
1330
1370
  stdio: "ignore",
@@ -1583,7 +1623,7 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
1583
1623
  socket.write(
1584
1624
  `${JSON.stringify({
1585
1625
  type: IPC_RESPONSE_TYPES.ERROR,
1586
- error: "launch_agent requires agent=codex|claude|ucode",
1626
+ error: "launch_agent requires agent=codex|claude|agy|ucode",
1587
1627
  })}
1588
1628
  `,
1589
1629
  );
@@ -1620,9 +1660,9 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
1620
1660
  : null,
1621
1661
  };
1622
1662
  let soloLaunchBootstrap = null;
1623
- if (requestedProfile && (normalizedAgent === "ufoo" || normalizedAgent === "claude" || normalizedAgent === "codex")) {
1624
- const agentTypeMap = { ufoo: "ufoo-code", claude: "claude-code", codex: "codex" };
1625
- const defaultNickMap = { ufoo: "ucode", claude: "claude", codex: "codex" };
1663
+ if (requestedProfile && (normalizedAgent === "ufoo" || normalizedAgent === "claude" || normalizedAgent === "codex" || normalizedAgent === "agy")) {
1664
+ const agentTypeMap = { ufoo: "ufoo-code", claude: "claude-code", codex: "codex", agy: "agy" };
1665
+ const defaultNickMap = { ufoo: "ucode", claude: "claude", codex: "codex", agy: "agy" };
1626
1666
  const agentTypeForBootstrap = agentTypeMap[normalizedAgent];
1627
1667
  const soloNickname = explicitNickname || defaultNickMap[normalizedAgent];
1628
1668
  const profileResult = resolveSoloPromptProfile(projectRoot, requestedProfile);
@@ -1667,6 +1707,12 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
1667
1707
  ...(Array.isArray(op.extra_args) ? op.extra_args : []),
1668
1708
  built.promptText,
1669
1709
  ];
1710
+ } else if (normalizedAgent === "agy") {
1711
+ // agy: bootstrap via -i (alias for --prompt-interactive)
1712
+ op.extra_args = [
1713
+ ...(Array.isArray(op.extra_args) ? op.extra_args : []),
1714
+ "-i", built.promptText,
1715
+ ];
1670
1716
  }
1671
1717
  soloLaunchBootstrap = {
1672
1718
  requested_profile: profileResult.requested_profile,
@@ -2246,7 +2292,7 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
2246
2292
  hostName,
2247
2293
  hostSessionId,
2248
2294
  hostCapabilities,
2249
- skipProbe,
2295
+ skipSessionResolve,
2250
2296
  } = req;
2251
2297
  if (!agentType) {
2252
2298
  socket.write(
@@ -2305,7 +2351,7 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
2305
2351
  reuseSessionId,
2306
2352
  reuseProviderSessionId,
2307
2353
  };
2308
- if (skipProbe) joinOptions.skipProbe = true;
2354
+ if (skipSessionResolve) joinOptions.skipSessionResolve = true;
2309
2355
 
2310
2356
  let finalNickname = nickname || "";
2311
2357
  let scopedNickname = applyProjectNicknamePrefix(projectRoot, finalNickname, {
@@ -2334,7 +2380,7 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
2334
2380
  eventBus.saveBusData();
2335
2381
  const resolvedNickname = resolveSubscriberNickname(projectRoot, subscriberId) || finalNickname || "";
2336
2382
 
2337
- if (!skipProbe && reuseProviderSessionId) {
2383
+ if (!skipSessionResolve && reuseProviderSessionId) {
2338
2384
  if (providerSessions) {
2339
2385
  providerSessions.set(subscriberId, {
2340
2386
  sessionId: reuseProviderSessionId,
@@ -2344,12 +2390,11 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
2344
2390
  }
2345
2391
  }
2346
2392
 
2347
- if (!skipProbe) {
2348
- const probeHandle = scheduleProviderSessionProbe({
2393
+ if (!skipSessionResolve) {
2394
+ const sessionResolveHandle = scheduleProviderSessionResolve({
2349
2395
  projectRoot,
2350
2396
  subscriberId,
2351
2397
  agentType,
2352
- nickname: resolvedNickname,
2353
2398
  agentCwd: projectRoot,
2354
2399
  onResolved: (id, resolved) => {
2355
2400
  if (providerSessions) {
@@ -2359,11 +2404,11 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
2359
2404
  updated_at: new Date().toISOString(),
2360
2405
  });
2361
2406
  }
2362
- probeHandles.delete(id);
2407
+ sessionResolveHandles.delete(id);
2363
2408
  },
2364
2409
  });
2365
- if (probeHandle) {
2366
- probeHandles.set(subscriberId, probeHandle);
2410
+ if (sessionResolveHandle) {
2411
+ sessionResolveHandles.set(subscriberId, sessionResolveHandle);
2367
2412
  }
2368
2413
  }
2369
2414
  socket.write(
@@ -2418,12 +2463,12 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
2418
2463
  updated_at: new Date().toISOString(),
2419
2464
  });
2420
2465
  }
2421
- // Cancel the scheduled probe to prevent redundant /ufoo injection
2422
- const handle = probeHandles.get(subscriberId);
2466
+ // Cancel the scheduled resolver; AGENT_READY already found the session file.
2467
+ const handle = sessionResolveHandles.get(subscriberId);
2423
2468
  if (handle && typeof handle.cancel === "function") {
2424
2469
  handle.cancel();
2425
2470
  }
2426
- probeHandles.delete(subscriberId);
2471
+ sessionResolveHandles.delete(subscriberId);
2427
2472
  return;
2428
2473
  }
2429
2474
 
@@ -2435,15 +2480,15 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
2435
2480
  }
2436
2481
  }
2437
2482
 
2438
- // Exhausted retries or no pid — fall back to scheduled probe
2439
- const probeHandle = probeHandles.get(subscriberId);
2440
- if (probeHandle && typeof probeHandle.triggerNow === "function") {
2441
- log(`agent_ready falling back to probe for ${subscriberId}`);
2442
- probeHandle.triggerNow().catch((err) => {
2443
- log(`agent_ready probe trigger failed for ${subscriberId}: ${err.message}`);
2483
+ // Exhausted retries or no pid — trigger the scheduled file resolver.
2484
+ const sessionResolveHandle = sessionResolveHandles.get(subscriberId);
2485
+ if (sessionResolveHandle && typeof sessionResolveHandle.triggerNow === "function") {
2486
+ log(`agent_ready triggering scheduled session resolver for ${subscriberId}`);
2487
+ sessionResolveHandle.triggerNow().catch((err) => {
2488
+ log(`agent_ready session resolver trigger failed for ${subscriberId}: ${err.message}`);
2444
2489
  });
2445
2490
  } else {
2446
- log(`agent_ready no probe handle found for ${subscriberId}`);
2491
+ log(`agent_ready no session resolver handle found for ${subscriberId}`);
2447
2492
  }
2448
2493
  };
2449
2494
 
@@ -2461,7 +2506,7 @@ function startDaemon({ projectRoot, provider, model, resumeMode = "auto" }) {
2461
2506
  log(`Started pid=${process.pid}`);
2462
2507
 
2463
2508
  // 清理旧 daemon 留下的孤儿 internal agent 进程
2464
- const EventBus = require("../bus");
2509
+ const EventBus = require("../../coordination/bus");
2465
2510
  const { spawnSync } = require("child_process");
2466
2511
  const eventBus = new EventBus(projectRoot);
2467
2512
  try {
@@ -2712,4 +2757,11 @@ function stopDaemon(projectRoot, options = {}) {
2712
2757
  return stopped;
2713
2758
  }
2714
2759
 
2715
- module.exports = { startDaemon, stopDaemon, isRunning, cleanupStaleState, socketPath };
2760
+ module.exports = {
2761
+ startDaemon,
2762
+ stopDaemon,
2763
+ isRunning,
2764
+ cleanupStaleState,
2765
+ socketPath,
2766
+ dispatchMessages,
2767
+ };
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  const net = require("net");
4
- const { IPC_RESPONSE_TYPES } = require("../shared/eventContract");
4
+ const { IPC_RESPONSE_TYPES } = require("../contracts/eventContract");
5
5
 
6
6
  function createDaemonIpcServer(options = {}) {
7
7
  const {
@@ -86,10 +86,13 @@ function stripProjectNicknamePrefix(projectRoot, nickname = "") {
86
86
 
87
87
  function resolveDisplayNickname(projectRoot, meta = {}, fallback = "") {
88
88
  const explicit = asTrimmedString(meta.nickname);
89
- if (explicit) {
90
- return meta.scoped_nickname ? explicit : stripProjectNicknamePrefix(projectRoot, explicit);
91
- }
92
89
  const scoped = asTrimmedString(meta.scoped_nickname);
90
+ // Always strip the project prefix off whichever nickname we settle on:
91
+ // group startup (groupOrchestrator) writes the scoped form into both
92
+ // `nickname` and `scoped_nickname`, so the previous "if scoped exists,
93
+ // return nickname as-is" shortcut surfaced the project-prefixed form to
94
+ // the UI instead of the short display name.
95
+ if (explicit) return stripProjectNicknamePrefix(projectRoot, explicit);
93
96
  if (scoped) return stripProjectNicknamePrefix(projectRoot, scoped);
94
97
  return asTrimmedString(fallback);
95
98
  }