@maintainer-pro/ai-cli 0.1.11 → 0.1.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/dist/index.cjs CHANGED
@@ -75,6 +75,7 @@ __export(index_exports, {
75
75
  hostAppsFingerprintForFolders: () => hostAppsFingerprintForFolders,
76
76
  inspectAndRepairWorkspace: () => inspectAndRepairWorkspace,
77
77
  inspectConfigOnly: () => inspectConfigOnly,
78
+ isAiServerApp: () => isAiServerApp,
78
79
  isDevMode: () => isDevMode,
79
80
  isIgnoredRelative: () => isIgnoredRelative,
80
81
  isInsideWorkspace: () => isInsideWorkspace,
@@ -109,6 +110,7 @@ __export(index_exports, {
109
110
  toNextRoute: () => toNextRoute,
110
111
  unionHostApps: () => unionHostApps,
111
112
  upsertManagedIgnoreFile: () => upsertManagedIgnoreFile,
113
+ withoutAiServerApp: () => withoutAiServerApp,
112
114
  writeCollaboraterApps: () => writeCollaboraterApps,
113
115
  writeHostAppsCache: () => writeHostAppsCache
114
116
  });
@@ -2895,6 +2897,9 @@ function dataInput(folder, extra) {
2895
2897
  function hostAppsCachePath2(folder, extra) {
2896
2898
  return hostAppsCachePath(dataInput(folder, extra));
2897
2899
  }
2900
+ function isAiServerApp(app) {
2901
+ return Boolean(app && (app.role === "ai-server" || app.id === AI_SERVER_APP_ID));
2902
+ }
2898
2903
  function defaultAiServerApp(port = AI_SERVER_DEFAULT_PORT) {
2899
2904
  return {
2900
2905
  id: AI_SERVER_APP_ID,
@@ -2956,24 +2961,17 @@ function normalizeHostApps(raw) {
2956
2961
  const apps = [];
2957
2962
  for (const item of raw) {
2958
2963
  const app = normalizeHostApp(item);
2959
- if (!app || seen.has(app.id)) continue;
2964
+ if (!app || isAiServerApp(app) || seen.has(app.id)) continue;
2960
2965
  seen.add(app.id);
2961
2966
  apps.push(app);
2962
2967
  }
2963
2968
  return apps;
2964
2969
  }
2965
- function ensureAiServerApp(apps, preferredPort = AI_SERVER_DEFAULT_PORT) {
2966
- const next = normalizeHostApps(apps);
2967
- const existing = next.find((app) => app.id === AI_SERVER_APP_ID || app.role === "ai-server");
2968
- if (existing) {
2969
- existing.id = AI_SERVER_APP_ID;
2970
- existing.role = "ai-server";
2971
- existing.locked = true;
2972
- existing.host = false;
2973
- existing.name = existing.name || "AI server";
2974
- return ensureSingleHost([existing, ...next.filter((app) => app !== existing)]);
2975
- }
2976
- return ensureSingleHost([defaultAiServerApp(preferredPort), ...next]);
2970
+ function withoutAiServerApp(apps) {
2971
+ return ensureSingleHost(normalizeHostApps(apps).filter((app) => !isAiServerApp(app)));
2972
+ }
2973
+ function ensureAiServerApp(apps, _preferredPort = AI_SERVER_DEFAULT_PORT) {
2974
+ return withoutAiServerApp(apps);
2977
2975
  }
2978
2976
  function readText(file) {
2979
2977
  try {
@@ -3215,10 +3213,6 @@ function detectHostAppsFromFiles(folder, opts = {}) {
3215
3213
  const apps = [];
3216
3214
  const envAi = parsePort(merged.AI_SERVER_PORT) || parsePort(merged.AI_SERVER_URL);
3217
3215
  const aiPort = envAi || parsePort(opts.preferredAiPort, AI_SERVER_DEFAULT_PORT);
3218
- apps.push({
3219
- ...defaultAiServerApp(aiPort),
3220
- source: envAi ? "env" : "default"
3221
- });
3222
3216
  const envPorts = {
3223
3217
  PORT: layers.filter((layer) => layer.file !== ".env.example").map((layer) => ({
3224
3218
  file: layer.file,
@@ -3324,7 +3318,7 @@ function detectHostAppsFromFiles(folder, opts = {}) {
3324
3318
  reasons.push("Found package.json scripts but no host app port in env or config");
3325
3319
  }
3326
3320
  return {
3327
- apps: ensureAiServerApp(tagged, aiPort),
3321
+ apps: withoutAiServerApp(tagged),
3328
3322
  reasons,
3329
3323
  confused: reasons.length > 0
3330
3324
  };
@@ -3345,10 +3339,7 @@ function detectHostAppsFromFolders(folders, opts = {}) {
3345
3339
  reasons.push(dirs.length > 1 ? `${base}: ${reason}` : reason);
3346
3340
  }
3347
3341
  for (const app of detected.apps) {
3348
- if (app.role === "ai-server") {
3349
- if (!apps.some((row) => row.role === "ai-server")) apps.push(app);
3350
- continue;
3351
- }
3342
+ if (isAiServerApp(app)) continue;
3352
3343
  let id = app.id;
3353
3344
  if (usedIds.has(id)) id = `${app.id}-${folderSlug(folder)}`;
3354
3345
  usedIds.add(id);
@@ -3368,7 +3359,7 @@ function detectHostAppsFromFolders(folders, opts = {}) {
3368
3359
  }
3369
3360
  }
3370
3361
  return {
3371
- apps: ensureAiServerApp(apps, opts.preferredAiPort),
3362
+ apps: withoutAiServerApp(apps),
3372
3363
  reasons,
3373
3364
  confused
3374
3365
  };
@@ -3589,13 +3580,7 @@ async function proposeHostAppsFromConfig(input) {
3589
3580
  inspected.name || input.appName || "App"
3590
3581
  );
3591
3582
  if (fromAi.length) {
3592
- apps = unionHostApps(
3593
- ensureAiServerApp(
3594
- [defaultAiServerApp(preferredAi), ...fromAi],
3595
- preferredAi
3596
- ),
3597
- detected.apps
3598
- );
3583
+ apps = unionHostApps(fromAi, detected.apps);
3599
3584
  }
3600
3585
  if (inspected.summary) projectSummary = inspected.summary;
3601
3586
  if (inspected.issues?.length) {
@@ -3679,10 +3664,7 @@ Return the real local ports and npm script names.`
3679
3664
  inspected.scripts,
3680
3665
  inspected.name || input.appName || "App"
3681
3666
  );
3682
- const apps2 = ensureAiServerApp(
3683
- [defaultAiServerApp(preferredAi), ...fromAi],
3684
- preferredAi
3685
- );
3667
+ const apps2 = withoutAiServerApp(fromAi);
3686
3668
  writeHostAppsCache(
3687
3669
  folder,
3688
3670
  apps2,
@@ -3778,6 +3760,7 @@ Return the real local ports and npm script names.`
3778
3760
  hostAppsFingerprintForFolders,
3779
3761
  inspectAndRepairWorkspace,
3780
3762
  inspectConfigOnly,
3763
+ isAiServerApp,
3781
3764
  isDevMode,
3782
3765
  isIgnoredRelative,
3783
3766
  isInsideWorkspace,
@@ -3812,6 +3795,7 @@ Return the real local ports and npm script names.`
3812
3795
  toNextRoute,
3813
3796
  unionHostApps,
3814
3797
  upsertManagedIgnoreFile,
3798
+ withoutAiServerApp,
3815
3799
  writeCollaboraterApps,
3816
3800
  writeHostAppsCache
3817
3801
  });
package/dist/index.d.cts CHANGED
@@ -601,11 +601,18 @@ declare function hostAppsCachePath(folder: string, extra?: {
601
601
  sandboxId?: string | null;
602
602
  dataDir?: string | null;
603
603
  }): string;
604
+ declare function isAiServerApp(app: Pick<HostApp, "id" | "role"> | null | undefined): boolean;
605
+ /** @deprecated Chat is in-process in the bridge, not a listed host app. */
604
606
  declare function defaultAiServerApp(port?: number): HostApp;
605
607
  declare function normalizeHostApp(raw: unknown): HostApp | null;
606
608
  declare function ensureSingleHost(apps: HostApp[]): HostApp[];
607
609
  declare function normalizeHostApps(raw: unknown): HostApp[];
608
- declare function ensureAiServerApp(apps: HostApp[], preferredPort?: number): HostApp[];
610
+ /** Chat is in-process in the bridge. Strips leftover ai-server rows. */
611
+ declare function withoutAiServerApp(apps: HostApp[]): HostApp[];
612
+ /**
613
+ * @deprecated Chat is not a listed host app. Strips leftover ai-server rows.
614
+ */
615
+ declare function ensureAiServerApp(apps: HostApp[], _preferredPort?: number): HostApp[];
609
616
  declare function readProjectEnvLayers(folder: string): {
610
617
  merged: Record<string, string>;
611
618
  layers: Array<{
@@ -662,4 +669,4 @@ declare function proposeHostAppsFromConfig(input: ProposeHostAppsInput): Promise
662
669
  */
663
670
  declare function resolveHostApps(input: HostAppsResolveInput): Promise<HostAppsResolveResult>;
664
671
 
665
- export { ACCESS_IGNORE_BEGIN, ACCESS_IGNORE_END, AI_SERVER_APP_ID, AI_SERVER_DEFAULT_PORT, type AiCliProviderId, type AiProvider, type AiResponse, COLLABORATER_DIR, type CachedChatMessage, type CachedConversation, type CallAiOptions, type ChatAttachment, type ChatHandlerOptions, type ChatHandlers, type ChatMessage, type ChatSenderType, type ChatStoreLike, type ChatUser, type ClientContext, DEFAULT_AI_IGNORE_PATHS, HOST_APPS_FILE, type HostApp, type HostAppAlternative, type HostAppRole, type HostAppSource, type HostAppsResolveInput, type HostAppsResolveResult, type LocalStoredMessage, MAINTAINER_PRO_HOME_DIR, type MaintainerProStoreOptions, PROMPT_SECTION, type ParentChainEntry, type ParentChainSource, type PriorConversationOptions, type ProjectDataInput, type ProposeHostAppsInput, type ProviderPreference, type SetupProposal, type SetupProposalConfidence, type SyncedChatStore, type SyncedChatStoreOptions, type SyncedStoreStats, type ToolCall, type ToolSchemaMap, WORKING_PROVIDER, type WorkingTurnEvent, type WorkspaceInspectInput, type WorkspaceInspectResult, type WorkspaceKind, buildClaudeUserPrompt, buildConversationPrompt, buildCursorPrompt, buildPriorConversationsContext, callAi, collectParentChain, commandExists, createAntigravityProvider, createBuiltinProviders, createChatHandler, createClaudeProvider, createCursorProvider, createDefaultSystemPrompt, createInfoLogger, createLocalDirectoryStore, createLogger, createMaintainerProStore, createMaintainerProStoreFromEnv, createSyncedChatStore, createToolValidator, defaultAiServerApp, detectHostAppsFromFiles, detectHostAppsFromFolders, ensureAiServerApp, ensureProjectDataDir, ensureSingleHost, formatAccessPolicyPromptSection, formatClientContext, formatParentChainContext, getProviderPreference, hostAppsCachePath, hostAppsFingerprint, hostAppsFingerprintForFolders, inspectAndRepairWorkspace, inspectConfigOnly, isDevMode, isIgnoredRelative, isInsideWorkspace, isPathAllowed, maintainerProHome, mergeDesiredHostApps, normalizeHostApp, normalizeHostApps, normalizeIgnorePaths, parentChainForTurn, parseAiResponse, parseIgnorePathsEnv, parsePort, previewText, hostAppsCachePath$1 as projectHostAppsPath, projectIdForFolder, projectUploadsDir, proposeHostAppsFromConfig, providerLabel, readCollaboraterApps, readHostAppsCache, readProjectEnvLayers, renderManagedIgnoreBlock, resolveCliBinary, resolveHostApps, resolveIgnorePaths, resolveLogLevel, resolveProjectDataDir, resolveProvider, sanitizeProjectId, saveChatAttachments, toNextRoute, unionHostApps, upsertManagedIgnoreFile, writeCollaboraterApps, writeHostAppsCache };
672
+ export { ACCESS_IGNORE_BEGIN, ACCESS_IGNORE_END, AI_SERVER_APP_ID, AI_SERVER_DEFAULT_PORT, type AiCliProviderId, type AiProvider, type AiResponse, COLLABORATER_DIR, type CachedChatMessage, type CachedConversation, type CallAiOptions, type ChatAttachment, type ChatHandlerOptions, type ChatHandlers, type ChatMessage, type ChatSenderType, type ChatStoreLike, type ChatUser, type ClientContext, DEFAULT_AI_IGNORE_PATHS, HOST_APPS_FILE, type HostApp, type HostAppAlternative, type HostAppRole, type HostAppSource, type HostAppsResolveInput, type HostAppsResolveResult, type LocalStoredMessage, MAINTAINER_PRO_HOME_DIR, type MaintainerProStoreOptions, PROMPT_SECTION, type ParentChainEntry, type ParentChainSource, type PriorConversationOptions, type ProjectDataInput, type ProposeHostAppsInput, type ProviderPreference, type SetupProposal, type SetupProposalConfidence, type SyncedChatStore, type SyncedChatStoreOptions, type SyncedStoreStats, type ToolCall, type ToolSchemaMap, WORKING_PROVIDER, type WorkingTurnEvent, type WorkspaceInspectInput, type WorkspaceInspectResult, type WorkspaceKind, buildClaudeUserPrompt, buildConversationPrompt, buildCursorPrompt, buildPriorConversationsContext, callAi, collectParentChain, commandExists, createAntigravityProvider, createBuiltinProviders, createChatHandler, createClaudeProvider, createCursorProvider, createDefaultSystemPrompt, createInfoLogger, createLocalDirectoryStore, createLogger, createMaintainerProStore, createMaintainerProStoreFromEnv, createSyncedChatStore, createToolValidator, defaultAiServerApp, detectHostAppsFromFiles, detectHostAppsFromFolders, ensureAiServerApp, ensureProjectDataDir, ensureSingleHost, formatAccessPolicyPromptSection, formatClientContext, formatParentChainContext, getProviderPreference, hostAppsCachePath, hostAppsFingerprint, hostAppsFingerprintForFolders, inspectAndRepairWorkspace, inspectConfigOnly, isAiServerApp, isDevMode, isIgnoredRelative, isInsideWorkspace, isPathAllowed, maintainerProHome, mergeDesiredHostApps, normalizeHostApp, normalizeHostApps, normalizeIgnorePaths, parentChainForTurn, parseAiResponse, parseIgnorePathsEnv, parsePort, previewText, hostAppsCachePath$1 as projectHostAppsPath, projectIdForFolder, projectUploadsDir, proposeHostAppsFromConfig, providerLabel, readCollaboraterApps, readHostAppsCache, readProjectEnvLayers, renderManagedIgnoreBlock, resolveCliBinary, resolveHostApps, resolveIgnorePaths, resolveLogLevel, resolveProjectDataDir, resolveProvider, sanitizeProjectId, saveChatAttachments, toNextRoute, unionHostApps, upsertManagedIgnoreFile, withoutAiServerApp, writeCollaboraterApps, writeHostAppsCache };
package/dist/index.d.ts CHANGED
@@ -601,11 +601,18 @@ declare function hostAppsCachePath(folder: string, extra?: {
601
601
  sandboxId?: string | null;
602
602
  dataDir?: string | null;
603
603
  }): string;
604
+ declare function isAiServerApp(app: Pick<HostApp, "id" | "role"> | null | undefined): boolean;
605
+ /** @deprecated Chat is in-process in the bridge, not a listed host app. */
604
606
  declare function defaultAiServerApp(port?: number): HostApp;
605
607
  declare function normalizeHostApp(raw: unknown): HostApp | null;
606
608
  declare function ensureSingleHost(apps: HostApp[]): HostApp[];
607
609
  declare function normalizeHostApps(raw: unknown): HostApp[];
608
- declare function ensureAiServerApp(apps: HostApp[], preferredPort?: number): HostApp[];
610
+ /** Chat is in-process in the bridge. Strips leftover ai-server rows. */
611
+ declare function withoutAiServerApp(apps: HostApp[]): HostApp[];
612
+ /**
613
+ * @deprecated Chat is not a listed host app. Strips leftover ai-server rows.
614
+ */
615
+ declare function ensureAiServerApp(apps: HostApp[], _preferredPort?: number): HostApp[];
609
616
  declare function readProjectEnvLayers(folder: string): {
610
617
  merged: Record<string, string>;
611
618
  layers: Array<{
@@ -662,4 +669,4 @@ declare function proposeHostAppsFromConfig(input: ProposeHostAppsInput): Promise
662
669
  */
663
670
  declare function resolveHostApps(input: HostAppsResolveInput): Promise<HostAppsResolveResult>;
664
671
 
665
- export { ACCESS_IGNORE_BEGIN, ACCESS_IGNORE_END, AI_SERVER_APP_ID, AI_SERVER_DEFAULT_PORT, type AiCliProviderId, type AiProvider, type AiResponse, COLLABORATER_DIR, type CachedChatMessage, type CachedConversation, type CallAiOptions, type ChatAttachment, type ChatHandlerOptions, type ChatHandlers, type ChatMessage, type ChatSenderType, type ChatStoreLike, type ChatUser, type ClientContext, DEFAULT_AI_IGNORE_PATHS, HOST_APPS_FILE, type HostApp, type HostAppAlternative, type HostAppRole, type HostAppSource, type HostAppsResolveInput, type HostAppsResolveResult, type LocalStoredMessage, MAINTAINER_PRO_HOME_DIR, type MaintainerProStoreOptions, PROMPT_SECTION, type ParentChainEntry, type ParentChainSource, type PriorConversationOptions, type ProjectDataInput, type ProposeHostAppsInput, type ProviderPreference, type SetupProposal, type SetupProposalConfidence, type SyncedChatStore, type SyncedChatStoreOptions, type SyncedStoreStats, type ToolCall, type ToolSchemaMap, WORKING_PROVIDER, type WorkingTurnEvent, type WorkspaceInspectInput, type WorkspaceInspectResult, type WorkspaceKind, buildClaudeUserPrompt, buildConversationPrompt, buildCursorPrompt, buildPriorConversationsContext, callAi, collectParentChain, commandExists, createAntigravityProvider, createBuiltinProviders, createChatHandler, createClaudeProvider, createCursorProvider, createDefaultSystemPrompt, createInfoLogger, createLocalDirectoryStore, createLogger, createMaintainerProStore, createMaintainerProStoreFromEnv, createSyncedChatStore, createToolValidator, defaultAiServerApp, detectHostAppsFromFiles, detectHostAppsFromFolders, ensureAiServerApp, ensureProjectDataDir, ensureSingleHost, formatAccessPolicyPromptSection, formatClientContext, formatParentChainContext, getProviderPreference, hostAppsCachePath, hostAppsFingerprint, hostAppsFingerprintForFolders, inspectAndRepairWorkspace, inspectConfigOnly, isDevMode, isIgnoredRelative, isInsideWorkspace, isPathAllowed, maintainerProHome, mergeDesiredHostApps, normalizeHostApp, normalizeHostApps, normalizeIgnorePaths, parentChainForTurn, parseAiResponse, parseIgnorePathsEnv, parsePort, previewText, hostAppsCachePath$1 as projectHostAppsPath, projectIdForFolder, projectUploadsDir, proposeHostAppsFromConfig, providerLabel, readCollaboraterApps, readHostAppsCache, readProjectEnvLayers, renderManagedIgnoreBlock, resolveCliBinary, resolveHostApps, resolveIgnorePaths, resolveLogLevel, resolveProjectDataDir, resolveProvider, sanitizeProjectId, saveChatAttachments, toNextRoute, unionHostApps, upsertManagedIgnoreFile, writeCollaboraterApps, writeHostAppsCache };
672
+ export { ACCESS_IGNORE_BEGIN, ACCESS_IGNORE_END, AI_SERVER_APP_ID, AI_SERVER_DEFAULT_PORT, type AiCliProviderId, type AiProvider, type AiResponse, COLLABORATER_DIR, type CachedChatMessage, type CachedConversation, type CallAiOptions, type ChatAttachment, type ChatHandlerOptions, type ChatHandlers, type ChatMessage, type ChatSenderType, type ChatStoreLike, type ChatUser, type ClientContext, DEFAULT_AI_IGNORE_PATHS, HOST_APPS_FILE, type HostApp, type HostAppAlternative, type HostAppRole, type HostAppSource, type HostAppsResolveInput, type HostAppsResolveResult, type LocalStoredMessage, MAINTAINER_PRO_HOME_DIR, type MaintainerProStoreOptions, PROMPT_SECTION, type ParentChainEntry, type ParentChainSource, type PriorConversationOptions, type ProjectDataInput, type ProposeHostAppsInput, type ProviderPreference, type SetupProposal, type SetupProposalConfidence, type SyncedChatStore, type SyncedChatStoreOptions, type SyncedStoreStats, type ToolCall, type ToolSchemaMap, WORKING_PROVIDER, type WorkingTurnEvent, type WorkspaceInspectInput, type WorkspaceInspectResult, type WorkspaceKind, buildClaudeUserPrompt, buildConversationPrompt, buildCursorPrompt, buildPriorConversationsContext, callAi, collectParentChain, commandExists, createAntigravityProvider, createBuiltinProviders, createChatHandler, createClaudeProvider, createCursorProvider, createDefaultSystemPrompt, createInfoLogger, createLocalDirectoryStore, createLogger, createMaintainerProStore, createMaintainerProStoreFromEnv, createSyncedChatStore, createToolValidator, defaultAiServerApp, detectHostAppsFromFiles, detectHostAppsFromFolders, ensureAiServerApp, ensureProjectDataDir, ensureSingleHost, formatAccessPolicyPromptSection, formatClientContext, formatParentChainContext, getProviderPreference, hostAppsCachePath, hostAppsFingerprint, hostAppsFingerprintForFolders, inspectAndRepairWorkspace, inspectConfigOnly, isAiServerApp, isDevMode, isIgnoredRelative, isInsideWorkspace, isPathAllowed, maintainerProHome, mergeDesiredHostApps, normalizeHostApp, normalizeHostApps, normalizeIgnorePaths, parentChainForTurn, parseAiResponse, parseIgnorePathsEnv, parsePort, previewText, hostAppsCachePath$1 as projectHostAppsPath, projectIdForFolder, projectUploadsDir, proposeHostAppsFromConfig, providerLabel, readCollaboraterApps, readHostAppsCache, readProjectEnvLayers, renderManagedIgnoreBlock, resolveCliBinary, resolveHostApps, resolveIgnorePaths, resolveLogLevel, resolveProjectDataDir, resolveProvider, sanitizeProjectId, saveChatAttachments, toNextRoute, unionHostApps, upsertManagedIgnoreFile, withoutAiServerApp, writeCollaboraterApps, writeHostAppsCache };
package/dist/index.js CHANGED
@@ -2779,6 +2779,9 @@ function dataInput(folder, extra) {
2779
2779
  function hostAppsCachePath2(folder, extra) {
2780
2780
  return hostAppsCachePath(dataInput(folder, extra));
2781
2781
  }
2782
+ function isAiServerApp(app) {
2783
+ return Boolean(app && (app.role === "ai-server" || app.id === AI_SERVER_APP_ID));
2784
+ }
2782
2785
  function defaultAiServerApp(port = AI_SERVER_DEFAULT_PORT) {
2783
2786
  return {
2784
2787
  id: AI_SERVER_APP_ID,
@@ -2840,24 +2843,17 @@ function normalizeHostApps(raw) {
2840
2843
  const apps = [];
2841
2844
  for (const item of raw) {
2842
2845
  const app = normalizeHostApp(item);
2843
- if (!app || seen.has(app.id)) continue;
2846
+ if (!app || isAiServerApp(app) || seen.has(app.id)) continue;
2844
2847
  seen.add(app.id);
2845
2848
  apps.push(app);
2846
2849
  }
2847
2850
  return apps;
2848
2851
  }
2849
- function ensureAiServerApp(apps, preferredPort = AI_SERVER_DEFAULT_PORT) {
2850
- const next = normalizeHostApps(apps);
2851
- const existing = next.find((app) => app.id === AI_SERVER_APP_ID || app.role === "ai-server");
2852
- if (existing) {
2853
- existing.id = AI_SERVER_APP_ID;
2854
- existing.role = "ai-server";
2855
- existing.locked = true;
2856
- existing.host = false;
2857
- existing.name = existing.name || "AI server";
2858
- return ensureSingleHost([existing, ...next.filter((app) => app !== existing)]);
2859
- }
2860
- return ensureSingleHost([defaultAiServerApp(preferredPort), ...next]);
2852
+ function withoutAiServerApp(apps) {
2853
+ return ensureSingleHost(normalizeHostApps(apps).filter((app) => !isAiServerApp(app)));
2854
+ }
2855
+ function ensureAiServerApp(apps, _preferredPort = AI_SERVER_DEFAULT_PORT) {
2856
+ return withoutAiServerApp(apps);
2861
2857
  }
2862
2858
  function readText(file) {
2863
2859
  try {
@@ -3099,10 +3095,6 @@ function detectHostAppsFromFiles(folder, opts = {}) {
3099
3095
  const apps = [];
3100
3096
  const envAi = parsePort(merged.AI_SERVER_PORT) || parsePort(merged.AI_SERVER_URL);
3101
3097
  const aiPort = envAi || parsePort(opts.preferredAiPort, AI_SERVER_DEFAULT_PORT);
3102
- apps.push({
3103
- ...defaultAiServerApp(aiPort),
3104
- source: envAi ? "env" : "default"
3105
- });
3106
3098
  const envPorts = {
3107
3099
  PORT: layers.filter((layer) => layer.file !== ".env.example").map((layer) => ({
3108
3100
  file: layer.file,
@@ -3208,7 +3200,7 @@ function detectHostAppsFromFiles(folder, opts = {}) {
3208
3200
  reasons.push("Found package.json scripts but no host app port in env or config");
3209
3201
  }
3210
3202
  return {
3211
- apps: ensureAiServerApp(tagged, aiPort),
3203
+ apps: withoutAiServerApp(tagged),
3212
3204
  reasons,
3213
3205
  confused: reasons.length > 0
3214
3206
  };
@@ -3229,10 +3221,7 @@ function detectHostAppsFromFolders(folders, opts = {}) {
3229
3221
  reasons.push(dirs.length > 1 ? `${base}: ${reason}` : reason);
3230
3222
  }
3231
3223
  for (const app of detected.apps) {
3232
- if (app.role === "ai-server") {
3233
- if (!apps.some((row) => row.role === "ai-server")) apps.push(app);
3234
- continue;
3235
- }
3224
+ if (isAiServerApp(app)) continue;
3236
3225
  let id = app.id;
3237
3226
  if (usedIds.has(id)) id = `${app.id}-${folderSlug(folder)}`;
3238
3227
  usedIds.add(id);
@@ -3252,7 +3241,7 @@ function detectHostAppsFromFolders(folders, opts = {}) {
3252
3241
  }
3253
3242
  }
3254
3243
  return {
3255
- apps: ensureAiServerApp(apps, opts.preferredAiPort),
3244
+ apps: withoutAiServerApp(apps),
3256
3245
  reasons,
3257
3246
  confused
3258
3247
  };
@@ -3473,13 +3462,7 @@ async function proposeHostAppsFromConfig(input) {
3473
3462
  inspected.name || input.appName || "App"
3474
3463
  );
3475
3464
  if (fromAi.length) {
3476
- apps = unionHostApps(
3477
- ensureAiServerApp(
3478
- [defaultAiServerApp(preferredAi), ...fromAi],
3479
- preferredAi
3480
- ),
3481
- detected.apps
3482
- );
3465
+ apps = unionHostApps(fromAi, detected.apps);
3483
3466
  }
3484
3467
  if (inspected.summary) projectSummary = inspected.summary;
3485
3468
  if (inspected.issues?.length) {
@@ -3563,10 +3546,7 @@ Return the real local ports and npm script names.`
3563
3546
  inspected.scripts,
3564
3547
  inspected.name || input.appName || "App"
3565
3548
  );
3566
- const apps2 = ensureAiServerApp(
3567
- [defaultAiServerApp(preferredAi), ...fromAi],
3568
- preferredAi
3569
- );
3549
+ const apps2 = withoutAiServerApp(fromAi);
3570
3550
  writeHostAppsCache(
3571
3551
  folder,
3572
3552
  apps2,
@@ -3661,6 +3641,7 @@ export {
3661
3641
  hostAppsFingerprintForFolders,
3662
3642
  inspectAndRepairWorkspace,
3663
3643
  inspectConfigOnly,
3644
+ isAiServerApp,
3664
3645
  isDevMode,
3665
3646
  isIgnoredRelative,
3666
3647
  isInsideWorkspace,
@@ -3695,6 +3676,7 @@ export {
3695
3676
  toNextRoute,
3696
3677
  unionHostApps,
3697
3678
  upsertManagedIgnoreFile,
3679
+ withoutAiServerApp,
3698
3680
  writeCollaboraterApps,
3699
3681
  writeHostAppsCache
3700
3682
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maintainer-pro/ai-cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Maintainer Pro server SDK: Claude/Cursor CLI, chat HTTP handlers, and optional SQL persistence",
5
5
  "keywords": [
6
6
  "maintainer-pro",