@iaforged/context-code 1.2.8 → 1.2.10

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 (172) hide show
  1. package/README.md +119 -119
  2. package/context-bootstrap.js +26 -26
  3. package/dist/src/QueryEngine.js +394 -327
  4. package/dist/src/bridge/bridgeUI.js +1 -1
  5. package/dist/src/buddy/prompt.js +4 -4
  6. package/dist/src/cli/handlers/auth.js +126 -9
  7. package/dist/src/cli/print.js +35 -1
  8. package/dist/src/commands/agent/agent.js +28 -2
  9. package/dist/src/commands/agent/agentStore.js +8 -1
  10. package/dist/src/commands/agent/index.js +1 -1
  11. package/dist/src/commands/bridge-kick.js +9 -9
  12. package/dist/src/commands/commit.js +34 -34
  13. package/dist/src/commands/init-verifiers.js +3 -3
  14. package/dist/src/commands/init.js +88 -88
  15. package/dist/src/commands/insights.js +787 -787
  16. package/dist/src/commands/install.js +19 -19
  17. package/dist/src/commands/login/login.js +21 -12
  18. package/dist/src/commands/logout/logout.js +9 -0
  19. package/dist/src/commands/model/model.js +9 -4
  20. package/dist/src/commands/orchestrate/SwarmUI.js +50 -0
  21. package/dist/src/commands/orchestrate/index.js +2 -2
  22. package/dist/src/commands/orchestrate/orchestrate.js +708 -12
  23. package/dist/src/commands/pr_comments/index.js +33 -33
  24. package/dist/src/commands/profile/index.js +1 -1
  25. package/dist/src/commands/profile/profile.js +52 -3
  26. package/dist/src/commands/provider/index.js +1 -1
  27. package/dist/src/commands/provider/provider.js +117 -45
  28. package/dist/src/commands/resumen/index.js +9 -0
  29. package/dist/src/commands/resumen/resumen.js +29 -0
  30. package/dist/src/commands/security-review.js +190 -190
  31. package/dist/src/commands/swarm-auto/index.js +9 -0
  32. package/dist/src/commands/swarm-auto/swarmAuto.js +111 -0
  33. package/dist/src/commands/swarm-init/index.js +9 -0
  34. package/dist/src/commands/swarm-init/swarmInit.js +72 -0
  35. package/dist/src/commands/team/team.js +39 -6
  36. package/dist/src/commands.js +14 -0
  37. package/dist/src/components/LogoV2/CondensedLogo.js +2 -2
  38. package/dist/src/components/PromptInput/PromptInputQueuedCommands.js +3 -3
  39. package/dist/src/components/agents/agentFileUtils.js +6 -6
  40. package/dist/src/components/permissions/hooks.js +5 -5
  41. package/dist/src/constants/outputStyles.js +83 -83
  42. package/dist/src/core/agents/blueprints.js +58 -0
  43. package/dist/src/core/agents/cliAdapter.js +61 -0
  44. package/dist/src/core/agents/registry.js +93 -0
  45. package/dist/src/core/agents/runtime.js +4 -0
  46. package/dist/src/core/agents/runtime.smoke.js +42 -0
  47. package/dist/src/core/agents/swarm.smoke.js +48 -0
  48. package/dist/src/core/agents/swarmTools.js +38 -0
  49. package/dist/src/core/auth/index.js +2 -0
  50. package/dist/src/core/auth/loginCliAdapter.js +24 -0
  51. package/dist/src/core/auth/loginCore.js +67 -0
  52. package/dist/src/core/auth/logoutCliAdapter.js +34 -0
  53. package/dist/src/core/auth/logoutCore.js +52 -0
  54. package/dist/src/core/auth/preflight.smoke.js +151 -0
  55. package/dist/src/core/index.js +21 -0
  56. package/dist/src/core/mcp/blueprints.js +27 -0
  57. package/dist/src/core/mcp/common.js +14 -0
  58. package/dist/src/core/mcp/runtime.js +67 -0
  59. package/dist/src/core/mcp/runtime.smoke.js +50 -0
  60. package/dist/src/core/mcp/swarmClient.js +40 -0
  61. package/dist/src/core/mcp/swarmSetup.js +43 -0
  62. package/dist/src/core/providers/cliAdapter.js +39 -0
  63. package/dist/src/core/providers/contracts.js +1 -0
  64. package/dist/src/core/providers/index.js +3 -0
  65. package/dist/src/core/providers/llmCore.js +123 -0
  66. package/dist/src/core/providers/providerCore.js +141 -0
  67. package/dist/src/core/providers/providerModelCompatibility.js +98 -0
  68. package/dist/src/core/providers/providerParitySmoke.js +83 -0
  69. package/dist/src/core/providers/providerProfileModelSmoke.js +80 -0
  70. package/dist/src/core/query/contracts.js +1 -0
  71. package/dist/src/core/query/runtime.js +117 -0
  72. package/dist/src/core/query/runtime.smoke.js +39 -0
  73. package/dist/src/core/query/timelineThinking.smoke.js +25 -0
  74. package/dist/src/core/query/wiring.smoke.js +76 -0
  75. package/dist/src/core/skills/cliAdapter.js +38 -0
  76. package/dist/src/core/skills/index.js +52 -0
  77. package/dist/src/core/skills/runtime.smoke.js +53 -0
  78. package/dist/src/core/tasks/runtime.js +205 -0
  79. package/dist/src/core/tasks/runtime.smoke.js +63 -0
  80. package/dist/src/core/tasks/sdkAdapter.js +4 -0
  81. package/dist/src/core/tools/contracts.js +3 -0
  82. package/dist/src/core/tools/fileResolution.js +112 -0
  83. package/dist/src/core/tools/fileResolution.smoke.js +33 -0
  84. package/dist/src/core/tools/filesCore.js +51 -0
  85. package/dist/src/core/tools/filesCore.smoke.js +108 -0
  86. package/dist/src/core/tools/gitCore.js +20 -0
  87. package/dist/src/core/tools/imageParity.smoke.js +36 -0
  88. package/dist/src/core/tools/notebookParity.smoke.js +68 -0
  89. package/dist/src/core/tools/registry.js +22 -0
  90. package/dist/src/core/tools/runtime.smoke.js +32 -0
  91. package/dist/src/core/tools/shellCore.js +60 -0
  92. package/dist/src/core/types/agentContext.js +9 -0
  93. package/dist/src/core/types/auth.js +3 -0
  94. package/dist/src/core/types/command.js +13 -0
  95. package/dist/src/core/types/provider.js +3 -0
  96. package/dist/src/core/types/sdkEvent.js +10 -0
  97. package/dist/src/core/types/swarm.js +1 -0
  98. package/dist/src/cost-tracker.js +3 -3
  99. package/dist/src/hooks/useAwaySummary.js +22 -9
  100. package/dist/src/main.js +32 -2
  101. package/dist/src/screens/REPL.js +9 -0
  102. package/dist/src/services/AgentSummary/agentSummary.js +10 -10
  103. package/dist/src/services/autoDream/autoDream.js +5 -5
  104. package/dist/src/services/autoDream/consolidationPrompt.js +49 -49
  105. package/dist/src/services/compact/prompt.js +238 -238
  106. package/dist/src/services/limits/sessionCounter.js +17 -17
  107. package/dist/src/services/mcp/client.js +27 -1
  108. package/dist/src/services/orchestration/execution/AgentTaskExecutor.js +39 -20
  109. package/dist/src/services/orchestration/execution/OrchestrationExecutionRuntime.js +65 -58
  110. package/dist/src/skills/bundled/loop.js +57 -57
  111. package/dist/src/skills/bundled/remember.js +53 -53
  112. package/dist/src/skills/bundled/simplify.js +49 -49
  113. package/dist/src/skills/bundled/skillify.js +2 -2
  114. package/dist/src/state/onChangeAppState.js +6 -0
  115. package/dist/src/tasks/LocalAgentTask/LocalAgentTask.js +5 -5
  116. package/dist/src/tasks/LocalMainSessionTask.js +5 -5
  117. package/dist/src/tasks/LocalShellTask/LocalShellTask.js +13 -13
  118. package/dist/src/tools/AgentTool/forkSubagent.js +25 -25
  119. package/dist/src/tools/AskUserQuestionTool/prompt.js +29 -29
  120. package/dist/src/tools/BashTool/BashTool.js +27 -2
  121. package/dist/src/tools/BriefTool/prompt.js +14 -14
  122. package/dist/src/tools/EnterPlanModeTool/EnterPlanModeTool.js +12 -12
  123. package/dist/src/tools/EnterPlanModeTool/prompt.js +140 -140
  124. package/dist/src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.js +18 -18
  125. package/dist/src/tools/ExitPlanModeTool/prompt.js +23 -23
  126. package/dist/src/tools/ExitWorktreeTool/prompt.js +29 -29
  127. package/dist/src/tools/FileEditTool/prompt.js +7 -7
  128. package/dist/src/tools/FileReadTool/FileReadTool.js +18 -1
  129. package/dist/src/tools/FileWriteTool/prompt.js +6 -6
  130. package/dist/src/tools/GlobTool/prompt.js +4 -4
  131. package/dist/src/tools/GrepTool/prompt.js +10 -10
  132. package/dist/src/tools/LSPTool/prompt.js +18 -18
  133. package/dist/src/tools/ListMcpResourcesTool/prompt.js +15 -15
  134. package/dist/src/tools/PowerShellTool/PowerShellTool.js +25 -2
  135. package/dist/src/tools/ReadMcpResourceTool/prompt.js +13 -13
  136. package/dist/src/tools/SendMessageTool/prompt.js +36 -36
  137. package/dist/src/tools/SkillTool/prompt.js +21 -21
  138. package/dist/src/tools/SleepTool/prompt.js +10 -10
  139. package/dist/src/tools/TaskCreateTool/prompt.js +41 -41
  140. package/dist/src/tools/TaskGetTool/prompt.js +21 -21
  141. package/dist/src/tools/TaskListTool/prompt.js +30 -30
  142. package/dist/src/tools/TaskOutputTool/TaskOutputTool.js +8 -8
  143. package/dist/src/tools/TaskStopTool/prompt.js +5 -5
  144. package/dist/src/tools/TaskUpdateTool/prompt.js +74 -74
  145. package/dist/src/tools/TodoWriteTool/prompt.js +178 -178
  146. package/dist/src/tools/ToolSearchTool/prompt.js +9 -9
  147. package/dist/src/tools/WebFetchTool/WebFetchTool.js +9 -9
  148. package/dist/src/tools/WebFetchTool/prompt.js +31 -31
  149. package/dist/src/tools/WebSearchTool/prompt.js +26 -26
  150. package/dist/src/utils/agentContext.js +2 -0
  151. package/dist/src/utils/agenticSessionSearch.js +38 -38
  152. package/dist/src/utils/config.js +2 -0
  153. package/dist/src/utils/genericProcessUtils.js +21 -21
  154. package/dist/src/utils/heapDumpService.js +4 -4
  155. package/dist/src/utils/mcpValidation.js +2 -2
  156. package/dist/src/utils/model/modelStrings.js +1 -1
  157. package/dist/src/utils/model/providers.js +5 -0
  158. package/dist/src/utils/orchestration/store/providerAgentStore.js +22 -22
  159. package/dist/src/utils/orchestration/store/providerWorkspaceStore.js +10 -10
  160. package/dist/src/utils/orchestration/store/runStore.js +68 -68
  161. package/dist/src/utils/orchestration/store/teamStore.js +28 -28
  162. package/dist/src/utils/permissions/permissionExplainer.js +6 -6
  163. package/dist/src/utils/permissions/permissionsDb.js +43 -43
  164. package/dist/src/utils/sdkEventQueue.js +2 -0
  165. package/dist/src/utils/secureStorage/sqliteStorage.js +12 -12
  166. package/dist/src/utils/standardMcp/common.js +15 -0
  167. package/dist/src/utils/standardMcp/setup.js +52 -0
  168. package/dist/src/utils/swarm/teammatePromptAddendum.js +10 -10
  169. package/dist/src/utils/task/framework.js +6 -6
  170. package/package.json +1 -1
  171. package/dist/src/commands/usage/index.js +0 -7
  172. package/dist/src/commands/usage/usage.js +0 -5
@@ -0,0 +1,38 @@
1
+ export const coreSendMessageTool = {
2
+ name: 'send_message',
3
+ description: 'Send a message to another specialist agent in parallel. Use this when you need multiple specialists to work on independent parts of a task.',
4
+ execute: async (input) => {
5
+ const { targetAgentId, instructions } = input;
6
+ if (typeof targetAgentId !== 'string' || typeof instructions !== 'string') {
7
+ return { success: false, error: 'targetAgentId and instructions are required strings.' };
8
+ }
9
+ return {
10
+ success: true,
11
+ data: {
12
+ mode: 'parallel',
13
+ targetAgentId,
14
+ instructions
15
+ },
16
+ output: `Message sent to ${targetAgentId}. Waiting for results...`
17
+ };
18
+ }
19
+ };
20
+ export const coreHandoffTool = {
21
+ name: 'handoff',
22
+ description: 'Transfer control of the conversation to another specialist. Use this when a single specialist is better suited to handle the entire user request from now on.',
23
+ execute: async (input) => {
24
+ const { targetAgentId, instructions } = input;
25
+ if (typeof targetAgentId !== 'string' || typeof instructions !== 'string') {
26
+ return { success: false, error: 'targetAgentId and instructions are required strings.' };
27
+ }
28
+ return {
29
+ success: true,
30
+ data: {
31
+ mode: 'handoff',
32
+ targetAgentId,
33
+ instructions
34
+ },
35
+ output: `Handing off control to ${targetAgentId}.`
36
+ };
37
+ }
38
+ };
@@ -0,0 +1,2 @@
1
+ export * from './loginCore.js';
2
+ export * from './logoutCore.js';
@@ -0,0 +1,24 @@
1
+ import { resetCostState } from '../../bootstrap/state.js';
2
+ import { clearTrustedDeviceToken, enrollTrustedDevice } from '../../bridge/trustedDevice.js';
3
+ import { refreshGrowthBookAfterAuthChange } from '../../services/analytics/growthbook.js';
4
+ import { refreshPolicyLimits } from '../../services/policyLimits/index.js';
5
+ import { refreshRemoteManagedSettings } from '../../services/remoteManagedSettings/index.js';
6
+ import { switchProviderPreference } from '../../utils/model/providerSwitch.js';
7
+ import { stripSignatureBlocks } from '../../utils/messages.js';
8
+ import { checkAndDisableAutoModeIfNeeded, checkAndDisableBypassPermissionsIfNeeded, resetAutoModeGateCheck, resetBypassPermissionsCheck, } from '../../utils/permissions/bypassPermissionsKillswitch.js';
9
+ import { resetUserCache } from '../../utils/user.js';
10
+ export const cliAuthLoginServices = {
11
+ resetCostState,
12
+ clearTrustedDeviceToken,
13
+ enrollTrustedDevice,
14
+ refreshGrowthBookAfterAuthChange,
15
+ refreshPolicyLimits,
16
+ refreshRemoteManagedSettings,
17
+ stripSignatureBlocks,
18
+ switchProviderPreference,
19
+ resetUserCache,
20
+ resetBypassPermissionsCheck,
21
+ resetAutoModeGateCheck,
22
+ checkAndDisableBypassPermissionsIfNeeded,
23
+ checkAndDisableAutoModeIfNeeded,
24
+ };
@@ -0,0 +1,67 @@
1
+ import { resetCostState } from '../../bootstrap/state.js';
2
+ import { clearTrustedDeviceToken, enrollTrustedDevice } from '../../bridge/trustedDevice.js';
3
+ import { refreshGrowthBookAfterAuthChange } from '../../services/analytics/growthbook.js';
4
+ import { refreshPolicyLimits } from '../../services/policyLimits/index.js';
5
+ import { refreshRemoteManagedSettings } from '../../services/remoteManagedSettings/index.js';
6
+ import { stripSignatureBlocks } from '../../utils/messages.js';
7
+ import { checkAndDisableAutoModeIfNeeded, checkAndDisableBypassPermissionsIfNeeded, resetAutoModeGateCheck, resetBypassPermissionsCheck, } from '../../utils/permissions/bypassPermissionsKillswitch.js';
8
+ import { switchProviderPreference } from '../../utils/model/providerSwitch.js';
9
+ import { resetUserCache } from '../../utils/user.js';
10
+ export function isCoreAuthEnabled() {
11
+ return process.env.CORE_AUTH_ENABLED === '1';
12
+ }
13
+ export function parseLoginProfileName(args) {
14
+ const trimmedArgs = args?.trim() ?? '';
15
+ if (!trimmedArgs)
16
+ return undefined;
17
+ const tokens = trimmedArgs.split(/\s+/).filter(Boolean);
18
+ const profileIdx = tokens.findIndex(t => t === '--profile' || t === '-p');
19
+ if (profileIdx !== -1 && tokens[profileIdx + 1])
20
+ return tokens[profileIdx + 1];
21
+ if (tokens.length > 0 && !tokens[0].startsWith('-'))
22
+ return tokens[0];
23
+ return undefined;
24
+ }
25
+ function resolveProvider(targetProvider) {
26
+ if (!targetProvider)
27
+ return 'claude';
28
+ return targetProvider;
29
+ }
30
+ export function applySuccessfulLogin(params) {
31
+ const { context, profileName, previousModel, previousProvider, targetProvider, transcriptClassifierEnabled, } = params;
32
+ context.onChangeAPIKey();
33
+ context.setMessages(stripSignatureBlocks);
34
+ const restoredModel = switchProviderPreference({
35
+ currentModel: previousModel,
36
+ currentProvider: previousProvider,
37
+ targetProvider: resolveProvider(targetProvider),
38
+ targetProfileName: profileName,
39
+ });
40
+ resetCostState();
41
+ void refreshRemoteManagedSettings();
42
+ void refreshPolicyLimits();
43
+ resetUserCache();
44
+ refreshGrowthBookAfterAuthChange();
45
+ clearTrustedDeviceToken();
46
+ void enrollTrustedDevice();
47
+ resetBypassPermissionsCheck();
48
+ const appState = context.getAppState();
49
+ void checkAndDisableBypassPermissionsIfNeeded(appState.toolPermissionContext, context.setAppState);
50
+ if (transcriptClassifierEnabled) {
51
+ resetAutoModeGateCheck();
52
+ void checkAndDisableAutoModeIfNeeded(appState.toolPermissionContext, context.setAppState, appState.fastMode);
53
+ }
54
+ context.setAppState(prev => ({
55
+ ...prev,
56
+ mainLoopModel: restoredModel,
57
+ mainLoopModelForSession: restoredModel,
58
+ authVersion: prev.authVersion + 1,
59
+ }));
60
+ const shouldOpenModelPicker = !restoredModel;
61
+ const message = shouldOpenModelPicker
62
+ ? profileName
63
+ ? `Inicio de sesion exitoso en el perfil "${profileName}". Selecciona ahora el modelo para este perfil.`
64
+ : 'Inicio de sesion exitoso. Selecciona ahora el modelo para este perfil.'
65
+ : 'Inicio de sesión exitoso';
66
+ return { restoredModel, message, shouldOpenModelPicker };
67
+ }
@@ -0,0 +1,34 @@
1
+ import { clearTrustedDeviceTokenCache } from '../../bridge/trustedDevice.js';
2
+ import { refreshGrowthBookAfterAuthChange } from '../../services/analytics/growthbook.js';
3
+ import { getGroveNoticeConfig, getGroveSettings } from '../../services/api/grove.js';
4
+ import { clearPolicyLimitsCache } from '../../services/policyLimits/index.js';
5
+ import { clearRemoteManagedSettingsCache } from '../../services/remoteManagedSettings/index.js';
6
+ import { getClaudeAIOAuthTokens, getOpenAIOAuthTokens, removeApiKey } from '../../utils/auth.js';
7
+ import { clearBetasCaches } from '../../utils/betas.js';
8
+ import { saveGlobalConfig } from '../../utils/config.js';
9
+ import { getSecureStorage } from '../../utils/secureStorage/index.js';
10
+ import { clearToolSchemaCache } from '../../utils/toolSchemaCache.js';
11
+ import { resetUserCache } from '../../utils/user.js';
12
+ async function cliClearAuthRelatedCaches() {
13
+ getClaudeAIOAuthTokens.cache?.clear?.();
14
+ getOpenAIOAuthTokens.cache?.clear?.();
15
+ clearTrustedDeviceTokenCache();
16
+ clearBetasCaches();
17
+ clearToolSchemaCache();
18
+ resetUserCache();
19
+ refreshGrowthBookAfterAuthChange();
20
+ getGroveNoticeConfig.cache?.clear?.();
21
+ getGroveSettings.cache?.clear?.();
22
+ await clearRemoteManagedSettingsCache();
23
+ await clearPolicyLimitsCache();
24
+ }
25
+ export const cliAuthLogoutServices = {
26
+ flushTelemetry: async () => {
27
+ const { flushTelemetry } = await import('../../utils/telemetry/instrumentation.js');
28
+ await flushTelemetry();
29
+ },
30
+ removeApiKey,
31
+ getSecureStorage,
32
+ saveGlobalConfig,
33
+ clearAuthRelatedCaches: cliClearAuthRelatedCaches,
34
+ };
@@ -0,0 +1,52 @@
1
+ import { clearTrustedDeviceTokenCache } from '../../bridge/trustedDevice.js';
2
+ import { refreshGrowthBookAfterAuthChange } from '../../services/analytics/growthbook.js';
3
+ import { getGroveNoticeConfig, getGroveSettings } from '../../services/api/grove.js';
4
+ import { clearPolicyLimitsCache } from '../../services/policyLimits/index.js';
5
+ import { clearRemoteManagedSettingsCache } from '../../services/remoteManagedSettings/index.js';
6
+ import { getClaudeAIOAuthTokens, getOpenAIOAuthTokens, removeApiKey } from '../../utils/auth.js';
7
+ import { clearBetasCaches } from '../../utils/betas.js';
8
+ import { saveGlobalConfig } from '../../utils/config.js';
9
+ import { getSecureStorage } from '../../utils/secureStorage/index.js';
10
+ import { clearToolSchemaCache } from '../../utils/toolSchemaCache.js';
11
+ import { resetUserCache } from '../../utils/user.js';
12
+ export function isCoreAuthEnabled() {
13
+ return process.env.CORE_AUTH_ENABLED === '1';
14
+ }
15
+ // clearing anything memoized that must be invalidated when user/session/auth changes
16
+ export async function clearAuthRelatedCachesCore() {
17
+ getClaudeAIOAuthTokens.cache?.clear?.();
18
+ getOpenAIOAuthTokens.cache?.clear?.();
19
+ clearTrustedDeviceTokenCache();
20
+ clearBetasCaches();
21
+ clearToolSchemaCache();
22
+ resetUserCache();
23
+ refreshGrowthBookAfterAuthChange();
24
+ getGroveNoticeConfig.cache?.clear?.();
25
+ getGroveSettings.cache?.clear?.();
26
+ await clearRemoteManagedSettingsCache();
27
+ await clearPolicyLimitsCache();
28
+ }
29
+ export async function performLogoutCore({ clearOnboarding = false, } = {}) {
30
+ const { flushTelemetry } = await import('../../utils/telemetry/instrumentation.js');
31
+ await flushTelemetry();
32
+ await removeApiKey();
33
+ const secureStorage = getSecureStorage();
34
+ secureStorage.delete();
35
+ await clearAuthRelatedCachesCore();
36
+ saveGlobalConfig(current => {
37
+ const updated = { ...current };
38
+ if (clearOnboarding) {
39
+ updated.hasCompletedOnboarding = false;
40
+ updated.subscriptionNoticeCount = 0;
41
+ updated.hasAvailableSubscription = false;
42
+ if (updated.customApiKeyResponses?.approved) {
43
+ updated.customApiKeyResponses = {
44
+ ...updated.customApiKeyResponses,
45
+ approved: [],
46
+ };
47
+ }
48
+ }
49
+ updated.oauthAccount = undefined;
50
+ return updated;
51
+ });
52
+ }
@@ -0,0 +1,151 @@
1
+ import assert from 'node:assert/strict';
2
+ import { readFileSync } from 'node:fs';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { applySuccessfulLogin, parseLoginArgs, parseLoginProfileName, } from './loginCore.js';
6
+ import { performLogoutCore } from './logoutCore.js';
7
+ function resolveCliSrcRoot() {
8
+ const here = dirname(fileURLToPath(import.meta.url));
9
+ const candidates = [
10
+ resolve(here, '..', '..', '..'), // CLI/src from tsx
11
+ resolve(here, '..', '..', '..', '..', 'src'), // CLI/dist/src from node
12
+ ];
13
+ for (const candidate of candidates) {
14
+ try {
15
+ readFileSync(resolve(candidate, 'commands.ts'), 'utf8');
16
+ return candidate;
17
+ }
18
+ catch {
19
+ // try next candidate
20
+ }
21
+ }
22
+ throw new Error('auth-preflight smoke: no se encontro CLI/src/commands.ts');
23
+ }
24
+ function resolveRepoRoot(cliSrcRoot) {
25
+ return resolve(cliSrcRoot, '..', '..');
26
+ }
27
+ function verifyCoreAuthOrchestration() {
28
+ const events = [];
29
+ const contextState = {
30
+ authVersion: 5,
31
+ toolPermissionContext: {},
32
+ fastMode: false,
33
+ };
34
+ const result = applySuccessfulLogin({
35
+ context: {
36
+ onChangeAPIKey: () => events.push('onChangeAPIKey'),
37
+ setMessages: () => events.push('setMessages'),
38
+ setAppState: updater => {
39
+ Object.assign(contextState, updater(contextState));
40
+ events.push('setAppState');
41
+ },
42
+ getAppState: () => contextState,
43
+ },
44
+ previousModel: 'old-model',
45
+ previousProvider: 'claude',
46
+ targetProvider: 'openai',
47
+ transcriptClassifierEnabled: true,
48
+ profileName: 'main',
49
+ }, {
50
+ resetCostState: () => events.push('resetCostState'),
51
+ clearTrustedDeviceToken: () => events.push('clearTrustedDeviceToken'),
52
+ enrollTrustedDevice: async () => events.push('enrollTrustedDevice'),
53
+ refreshGrowthBookAfterAuthChange: () => events.push('refreshGrowthBook'),
54
+ refreshPolicyLimits: async () => events.push('refreshPolicyLimits'),
55
+ refreshRemoteManagedSettings: async () => events.push('refreshRemoteManagedSettings'),
56
+ stripSignatureBlocks: messages => messages,
57
+ switchProviderPreference: () => 'restored-model',
58
+ resetUserCache: () => events.push('resetUserCache'),
59
+ resetBypassPermissionsCheck: () => events.push('resetBypassPermissions'),
60
+ resetAutoModeGateCheck: () => events.push('resetAutoModeGateCheck'),
61
+ checkAndDisableBypassPermissionsIfNeeded: async () => events.push('checkBypass'),
62
+ checkAndDisableAutoModeIfNeeded: async () => events.push('checkAutoMode'),
63
+ });
64
+ assert.equal(result.restoredModel, 'restored-model');
65
+ assert.equal(result.shouldOpenModelPicker, false);
66
+ assert.equal(result.message, 'Inicio de sesion exitoso');
67
+ assert.equal(contextState.mainLoopModel, 'restored-model');
68
+ assert.equal(contextState.mainLoopModelForSession, 'restored-model');
69
+ assert.equal(contextState.authVersion, 6);
70
+ assert.ok(events.includes('onChangeAPIKey'));
71
+ assert.ok(events.includes('resetCostState'));
72
+ assert.equal(parseLoginProfileName('--profile work'), 'work');
73
+ assert.equal(parseLoginProfileName('-p team'), 'team');
74
+ assert.equal(parseLoginProfileName('direct-profile'), 'direct-profile');
75
+ assert.equal(parseLoginArgs('openai').provider, 'openai');
76
+ assert.equal(parseLoginArgs('gemini-google --profile corp').provider, 'gemini-google');
77
+ assert.equal(parseLoginArgs('gemini-google --profile corp').profileName, 'corp');
78
+ assert.equal(parseLoginArgs('openrouter').profileName, undefined);
79
+ }
80
+ async function verifyCoreLogoutOrchestration() {
81
+ let flushCalls = 0;
82
+ let removeApiKeyCalls = 0;
83
+ let secureDeleteCalls = 0;
84
+ let clearCacheCalls = 0;
85
+ let saveConfigCalls = 0;
86
+ await performLogoutCore({ clearOnboarding: true }, {
87
+ flushTelemetry: async () => {
88
+ flushCalls += 1;
89
+ },
90
+ removeApiKey: async () => {
91
+ removeApiKeyCalls += 1;
92
+ },
93
+ getSecureStorage: () => ({
94
+ delete: () => {
95
+ secureDeleteCalls += 1;
96
+ },
97
+ read: () => undefined,
98
+ }),
99
+ saveGlobalConfig: updater => {
100
+ const next = updater({
101
+ customApiKeyResponses: { approved: ['a'] },
102
+ });
103
+ saveConfigCalls += 1;
104
+ assert.equal(next.hasCompletedOnboarding, false);
105
+ assert.equal(next.subscriptionNoticeCount, 0);
106
+ assert.equal(next.hasAvailableSubscription, false);
107
+ },
108
+ clearAuthRelatedCaches: async () => {
109
+ clearCacheCalls += 1;
110
+ },
111
+ });
112
+ assert.equal(flushCalls, 1);
113
+ assert.equal(removeApiKeyCalls, 1);
114
+ assert.equal(secureDeleteCalls, 1);
115
+ assert.equal(clearCacheCalls, 1);
116
+ assert.equal(saveConfigCalls, 1);
117
+ }
118
+ function verifyCliAuthWiring(cliSrcRoot, repoRoot) {
119
+ const loginSrc = readFileSync(resolve(cliSrcRoot, 'commands', 'login', 'login.tsx'), 'utf8');
120
+ assert.ok(loginSrc.includes("from '../../core/auth/loginCore.js'"), 'login.tsx no importa core/auth/loginCore');
121
+ assert.ok(loginSrc.includes('cliAuthLoginServices'), 'login.tsx no usa cliAuthLoginServices');
122
+ assert.ok(/applySuccessfulLogin\([\s\S]*cliAuthLoginServices\)/.test(loginSrc), 'login.tsx no llama applySuccessfulLogin con services core');
123
+ const logoutSrc = readFileSync(resolve(cliSrcRoot, 'commands', 'logout', 'logout.tsx'), 'utf8');
124
+ assert.ok(logoutSrc.includes("from '../../core/auth/logoutCore.js'"), 'logout.tsx no importa core/auth/logoutCore');
125
+ assert.ok(logoutSrc.includes('cliAuthLogoutServices'), 'logout.tsx no usa cliAuthLogoutServices');
126
+ assert.ok(/performLogoutCore\(\{ clearOnboarding \}, cliAuthLogoutServices\)/.test(logoutSrc), 'logout.tsx no usa performLogoutCore con services core');
127
+ const commandsSrc = readFileSync(resolve(cliSrcRoot, 'commands.ts'), 'utf8');
128
+ assert.ok(commandsSrc.includes('logout,'), 'commands.ts no registra /logout');
129
+ assert.ok(commandsSrc.includes('login()'), 'commands.ts no registra /login');
130
+ const tauriMainSrc = readFileSync(resolve(repoRoot, 'apps', 'desktop', 'src-tauri', 'src', 'main.rs'), 'utf8');
131
+ assert.ok(tauriMainSrc.includes('fn core_auth_status('), 'main.rs no expone core_auth_status');
132
+ assert.ok(tauriMainSrc.includes('fn core_auth_login_start('), 'main.rs no expone core_auth_login_start');
133
+ assert.ok(tauriMainSrc.includes('fn core_auth_login_complete('), 'main.rs no expone core_auth_login_complete');
134
+ assert.ok(tauriMainSrc.includes('fn core_auth_logout('), 'main.rs no expone core_auth_logout');
135
+ assert.ok(tauriMainSrc.includes('core_auth_status,'), 'main.rs invoke_handler no registra core_auth_status');
136
+ assert.ok(tauriMainSrc.includes('core_auth_login_start,'), 'main.rs invoke_handler no registra core_auth_login_start');
137
+ assert.ok(tauriMainSrc.includes('core_auth_login_complete,'), 'main.rs invoke_handler no registra core_auth_login_complete');
138
+ assert.ok(tauriMainSrc.includes('core_auth_logout,'), 'main.rs invoke_handler no registra core_auth_logout');
139
+ }
140
+ export async function runAuthPreflightSmoke() {
141
+ const cliSrcRoot = resolveCliSrcRoot();
142
+ const repoRoot = resolveRepoRoot(cliSrcRoot);
143
+ verifyCoreAuthOrchestration();
144
+ await verifyCoreLogoutOrchestration();
145
+ verifyCliAuthWiring(cliSrcRoot, repoRoot);
146
+ }
147
+ const isDirectRun = process.argv[1]?.endsWith('preflight.smoke.js');
148
+ if (isDirectRun) {
149
+ await runAuthPreflightSmoke();
150
+ console.log('auth preflight smoke: ok');
151
+ }
@@ -0,0 +1,21 @@
1
+ // Stable shared surfaces already consumed by adapters.
2
+ export * from './auth/index.js';
3
+ export * from './providers/index.js';
4
+ // Query contracts are part of the public adapter surface.
5
+ export * from './query/contracts.js';
6
+ export * from './query/runtime.js';
7
+ // Tools migrated into core with usable execution contracts.
8
+ export * from './tools/contracts.js';
9
+ export * from './tools/registry.js';
10
+ export * from './tools/filesCore.js';
11
+ export * from './tools/shellCore.js';
12
+ export * from './tools/gitCore.js';
13
+ // MCP/skills/agents/tasks are exposed for incremental adoption.
14
+ // Their presence here does not imply Fase 6 thin-client closure by itself.
15
+ export * from './mcp/runtime.js';
16
+ export * from './skills/index.js';
17
+ // Downstream consumers may opt into these provisional runtimes explicitly.
18
+ export * from './agents/registry.js';
19
+ export * from './agents/runtime.js';
20
+ export * from './tasks/runtime.js';
21
+ export * from './tasks/sdkAdapter.js';
@@ -0,0 +1,27 @@
1
+ export const SWARM_MCP_BLUEPRINTS = [
2
+ {
3
+ name: 'google-search',
4
+ command: 'npx',
5
+ args: ['-y', '@modelcontextprotocol/server-google-search'],
6
+ description: 'Buscador web para el Deep Research Agent. Requiere GOOGLE_API_KEY.',
7
+ env: { GOOGLE_API_KEY: '' } // Usuario debe proveerla
8
+ },
9
+ {
10
+ name: 'filesystem',
11
+ command: 'npx',
12
+ args: ['-y', '@modelcontextprotocol/server-filesystem', '.'],
13
+ description: 'Acceso al sistema de archivos para Docs Agent y Data Analyst.'
14
+ },
15
+ {
16
+ name: 'sequential-thinking',
17
+ command: 'npx',
18
+ args: ['-y', '@modelcontextprotocol/server-sequential-thinking'],
19
+ description: 'Pensamiento secuencial para el Orquestador.'
20
+ },
21
+ {
22
+ name: 'memory',
23
+ command: 'npx',
24
+ args: ['-y', '@modelcontextprotocol/server-memory'],
25
+ description: 'Memoria compartida para que los agentes recuerden interacciones previas.'
26
+ }
27
+ ];
@@ -0,0 +1,14 @@
1
+ export const SWARM_MCP_SERVER_NAMES = {
2
+ SEARCH: 'duckduckgo',
3
+ THINKING: 'sequential-thinking',
4
+ MEMORY: 'memory',
5
+ FILESYSTEM: 'filesystem',
6
+ DATABASE: 'database'
7
+ };
8
+ export const SWARM_MCP_TOOLS = {
9
+ [SWARM_MCP_SERVER_NAMES.SEARCH]: ['duckduckgo_search'],
10
+ [SWARM_MCP_SERVER_NAMES.THINKING]: ['sequential_thinking'],
11
+ [SWARM_MCP_SERVER_NAMES.MEMORY]: ['create_entities', 'create_relations', 'read_graph', 'search_nodes', 'open_nodes'],
12
+ [SWARM_MCP_SERVER_NAMES.FILESYSTEM]: ['read_file', 'write_file', 'list_dir', 'move_file', 'search_files'],
13
+ [SWARM_MCP_SERVER_NAMES.DATABASE]: ['db_connect', 'db_query', 'db_execute', 'db_list_tables', 'db_describe_table']
14
+ };
@@ -0,0 +1,67 @@
1
+ function toCoreStatus(connection) {
2
+ switch (connection.type) {
3
+ case 'connected':
4
+ case 'failed':
5
+ case 'needs-auth':
6
+ case 'pending':
7
+ case 'disabled':
8
+ return connection.type;
9
+ }
10
+ }
11
+ export function isCoreMcpEnabled() {
12
+ return process.env.CORE_MCP_ENABLED === '1';
13
+ }
14
+ export class CoreMcpRuntime {
15
+ servers = new Map();
16
+ upsertServer(connection, extras) {
17
+ const existing = this.servers.get(connection.name);
18
+ const snapshot = {
19
+ id: connection.name,
20
+ name: connection.name,
21
+ status: toCoreStatus(connection),
22
+ transport: connection.config.type,
23
+ scope: connection.config.scope,
24
+ toolNames: extras?.tools?.map(tool => tool.name) ?? existing?.toolNames ?? [],
25
+ commandNames: extras?.commands?.map(command => command.name) ??
26
+ existing?.commandNames ??
27
+ [],
28
+ resourceCount: extras?.resources?.length ?? existing?.resourceCount ?? 0,
29
+ };
30
+ this.servers.set(connection.name, snapshot);
31
+ return snapshot;
32
+ }
33
+ updateServerTools(name, tools) {
34
+ const existing = this.servers.get(name);
35
+ if (!existing) {
36
+ return;
37
+ }
38
+ existing.toolNames = tools.map(tool => tool.name);
39
+ }
40
+ updateServerCommands(name, commands) {
41
+ const existing = this.servers.get(name);
42
+ if (!existing) {
43
+ return;
44
+ }
45
+ existing.commandNames = commands.map(command => command.name);
46
+ }
47
+ updateServerResources(name, resources) {
48
+ const existing = this.servers.get(name);
49
+ if (!existing) {
50
+ return;
51
+ }
52
+ existing.resourceCount = resources.length;
53
+ }
54
+ removeServer(name) {
55
+ this.servers.delete(name);
56
+ }
57
+ reset() {
58
+ this.servers.clear();
59
+ }
60
+ getServer(name) {
61
+ return this.servers.get(name);
62
+ }
63
+ listServers() {
64
+ return Array.from(this.servers.values());
65
+ }
66
+ }
67
+ export const coreMcpRuntime = new CoreMcpRuntime();
@@ -0,0 +1,50 @@
1
+ import assert from 'node:assert/strict';
2
+ import { CoreMcpRuntime, isCoreMcpEnabled } from './runtime.js';
3
+ const runtime = new CoreMcpRuntime();
4
+ const config = {
5
+ type: 'stdio',
6
+ command: 'node',
7
+ args: ['server.js'],
8
+ env: {},
9
+ cwd: process.cwd(),
10
+ scope: 'local',
11
+ };
12
+ const connected = {
13
+ type: 'connected',
14
+ name: 'demo-mcp',
15
+ config,
16
+ client: {},
17
+ initializedAt: Date.now(),
18
+ };
19
+ runtime.upsertServer(connected, {
20
+ tools: [{ name: 'mcp__demo__tool' }],
21
+ commands: [{ name: '/demo' }],
22
+ resources: [{ server: 'demo-mcp', uri: 'memory://a', name: 'A' }],
23
+ });
24
+ let snapshot = runtime.getServer('demo-mcp');
25
+ assert.ok(snapshot);
26
+ assert.equal(snapshot?.status, 'connected');
27
+ assert.equal(snapshot?.toolNames.length, 1);
28
+ assert.equal(snapshot?.commandNames.length, 1);
29
+ assert.equal(snapshot?.resourceCount, 1);
30
+ runtime.updateServerTools('demo-mcp', [{ name: 'mcp__demo__next' }]);
31
+ runtime.updateServerCommands('demo-mcp', [{ name: '/demo-next' }]);
32
+ runtime.updateServerResources('demo-mcp', [
33
+ { server: 'demo-mcp', uri: 'memory://b', name: 'B' },
34
+ { server: 'demo-mcp', uri: 'memory://c', name: 'C' },
35
+ ]);
36
+ snapshot = runtime.getServer('demo-mcp');
37
+ assert.equal(snapshot?.toolNames[0], 'mcp__demo__next');
38
+ assert.equal(snapshot?.commandNames[0], '/demo-next');
39
+ assert.equal(snapshot?.resourceCount, 2);
40
+ runtime.removeServer('demo-mcp');
41
+ assert.equal(runtime.listServers().length, 0);
42
+ runtime.upsertServer({
43
+ ...connected,
44
+ type: 'needs-auth',
45
+ });
46
+ assert.equal(runtime.getServer('demo-mcp')?.status, 'needs-auth');
47
+ runtime.reset();
48
+ assert.equal(runtime.listServers().length, 0);
49
+ assert.equal(typeof isCoreMcpEnabled(), 'boolean');
50
+ console.log('mcp.runtime.smoke PASS');
@@ -0,0 +1,40 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
3
+ export class SwarmMcpClient {
4
+ clients = new Map();
5
+ async connectToServer(name, command, args, env) {
6
+ const transport = new StdioClientTransport({
7
+ command,
8
+ args,
9
+ env: { ...process.env, ...env }
10
+ });
11
+ const client = new Client({
12
+ name: `swarm-${name}`,
13
+ version: '1.0.0'
14
+ }, {
15
+ capabilities: {}
16
+ });
17
+ await client.connect(transport);
18
+ this.clients.set(name, client);
19
+ return client;
20
+ }
21
+ async listTools() {
22
+ const allTools = [];
23
+ for (const [name, client] of this.clients) {
24
+ const result = await client.listTools();
25
+ allTools.push(...result.tools.map(t => ({
26
+ ...t,
27
+ name: `${name}__${t.name}`
28
+ })));
29
+ }
30
+ return allTools;
31
+ }
32
+ async callTool(fullName, args) {
33
+ const [serverName, toolName] = fullName.split('__');
34
+ const client = this.clients.get(serverName);
35
+ if (!client)
36
+ throw new Error(`Server ${serverName} not found`);
37
+ return await client.callTool({ name: toolName, arguments: args });
38
+ }
39
+ }
40
+ export const swarmMcpClient = new SwarmMcpClient();
@@ -0,0 +1,43 @@
1
+ import { buildMcpToolName } from '../../services/mcp/mcpStringUtils.js';
2
+ import { SWARM_MCP_SERVER_NAMES, SWARM_MCP_TOOLS } from './common.js';
3
+ export function setupSwarmMCPs() {
4
+ const mcpConfig = {};
5
+ const allowedTools = [];
6
+ // 1. Sequential Thinking (Siempre activo para el Orquestador)
7
+ mcpConfig[SWARM_MCP_SERVER_NAMES.THINKING] = {
8
+ type: 'stdio',
9
+ command: 'npx',
10
+ args: ['-y', '@modelcontextprotocol/server-sequential-thinking'],
11
+ scope: 'dynamic'
12
+ };
13
+ allowedTools.push(...SWARM_MCP_TOOLS[SWARM_MCP_SERVER_NAMES.THINKING].map(t => buildMcpToolName(SWARM_MCP_SERVER_NAMES.THINKING, t)));
14
+ // 2. Memory (Siempre activo para coherencia)
15
+ mcpConfig[SWARM_MCP_SERVER_NAMES.MEMORY] = {
16
+ type: 'stdio',
17
+ command: 'npx',
18
+ args: ['-y', '@modelcontextprotocol/server-memory'],
19
+ scope: 'dynamic'
20
+ };
21
+ allowedTools.push(...SWARM_MCP_TOOLS[SWARM_MCP_SERVER_NAMES.MEMORY].map(t => buildMcpToolName(SWARM_MCP_SERVER_NAMES.MEMORY, t)));
22
+ // 3. Filesystem (Solo si estamos en un directorio seguro)
23
+ mcpConfig[SWARM_MCP_SERVER_NAMES.FILESYSTEM] = {
24
+ type: 'stdio',
25
+ command: 'npx',
26
+ args: ['-y', '@modelcontextprotocol/server-filesystem', '.'],
27
+ scope: 'dynamic'
28
+ };
29
+ allowedTools.push(...SWARM_MCP_TOOLS[SWARM_MCP_SERVER_NAMES.FILESYSTEM].map(t => buildMcpToolName(SWARM_MCP_SERVER_NAMES.FILESYSTEM, t)));
30
+ // 4. Google Search (Solo si hay API KEY)
31
+ const googleApiKey = process.env.GOOGLE_API_KEY;
32
+ if (googleApiKey) {
33
+ mcpConfig[SWARM_MCP_SERVER_NAMES.SEARCH] = {
34
+ type: 'stdio',
35
+ command: 'npx',
36
+ args: ['-y', '@modelcontextprotocol/server-google-search'],
37
+ env: { GOOGLE_API_KEY: googleApiKey },
38
+ scope: 'dynamic'
39
+ };
40
+ allowedTools.push(...SWARM_MCP_TOOLS[SWARM_MCP_SERVER_NAMES.SEARCH].map(t => buildMcpToolName(SWARM_MCP_SERVER_NAMES.SEARCH, t)));
41
+ }
42
+ return { mcpConfig, allowedTools };
43
+ }