@iaforged/context-code 1.2.9 → 1.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/README.md +119 -119
  2. package/context-bootstrap.js +28 -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
@@ -1,39 +1,39 @@
1
1
  export const WEB_FETCH_TOOL_NAME = 'WebFetch';
2
- export const DESCRIPTION = `
3
- - Fetches content from a specified URL and processes it using an AI model
4
- - Takes a URL and a prompt as input
5
- - Fetches the URL content, converts HTML to markdown
6
- - Processes the content with the prompt using a small, fast model
7
- - Returns the model's response about the content
8
- - Use this tool when you need to retrieve and analyze web content
9
-
10
- Usage notes:
11
- - IMPORTANT: If an MCP-provided web fetch tool is available, prefer using that tool instead of this one, as it may have fewer restrictions.
12
- - The URL must be a fully-formed valid URL
13
- - HTTP URLs will be automatically upgraded to HTTPS
14
- - The prompt should describe what information you want to extract from the page
15
- - This tool is read-only and does not modify any files
16
- - Results may be summarized if the content is very large
17
- - Includes a self-cleaning 15-minute cache for faster responses when repeatedly accessing the same URL
18
- - When a URL redirects to a different host, the tool will inform you and provide the redirect URL in a special format. You should then make a new WebFetch request with the redirect URL to fetch the content.
19
- - For GitHub URLs, prefer using the gh CLI via Bash instead (e.g., gh pr view, gh issue view, gh api).
2
+ export const DESCRIPTION = `
3
+ - Fetches content from a specified URL and processes it using an AI model
4
+ - Takes a URL and a prompt as input
5
+ - Fetches the URL content, converts HTML to markdown
6
+ - Processes the content with the prompt using a small, fast model
7
+ - Returns the model's response about the content
8
+ - Use this tool when you need to retrieve and analyze web content
9
+
10
+ Usage notes:
11
+ - IMPORTANT: If an MCP-provided web fetch tool is available, prefer using that tool instead of this one, as it may have fewer restrictions.
12
+ - The URL must be a fully-formed valid URL
13
+ - HTTP URLs will be automatically upgraded to HTTPS
14
+ - The prompt should describe what information you want to extract from the page
15
+ - This tool is read-only and does not modify any files
16
+ - Results may be summarized if the content is very large
17
+ - Includes a self-cleaning 15-minute cache for faster responses when repeatedly accessing the same URL
18
+ - When a URL redirects to a different host, the tool will inform you and provide the redirect URL in a special format. You should then make a new WebFetch request with the redirect URL to fetch the content.
19
+ - For GitHub URLs, prefer using the gh CLI via Bash instead (e.g., gh pr view, gh issue view, gh api).
20
20
  `;
21
21
  export function makeSecondaryModelPrompt(markdownContent, prompt, isPreapprovedDomain) {
22
22
  const guidelines = isPreapprovedDomain
23
23
  ? `Provide a concise response based on the content above. Include relevant details, code examples, and documentation excerpts as needed.`
24
- : `Provide a concise response based only on the content above. In your response:
25
- - Enforce a strict 125-character maximum for quotes from any source document. Open Source Software is ok as long as we respect the license.
26
- - Use quotation marks for exact language from articles; any language outside of the quotation should never be word-for-word the same.
27
- - You are not a lawyer and never comment on the legality of your own prompts and responses.
24
+ : `Provide a concise response based only on the content above. In your response:
25
+ - Enforce a strict 125-character maximum for quotes from any source document. Open Source Software is ok as long as we respect the license.
26
+ - Use quotation marks for exact language from articles; any language outside of the quotation should never be word-for-word the same.
27
+ - You are not a lawyer and never comment on the legality of your own prompts and responses.
28
28
  - Never produce or reproduce exact song lyrics.`;
29
- return `
30
- Web page content:
31
- ---
32
- ${markdownContent}
33
- ---
34
-
35
- ${prompt}
36
-
37
- ${guidelines}
29
+ return `
30
+ Web page content:
31
+ ---
32
+ ${markdownContent}
33
+ ---
34
+
35
+ ${prompt}
36
+
37
+ ${guidelines}
38
38
  `;
39
39
  }
@@ -2,31 +2,31 @@ import { getLocalMonthYear } from '../../constants/common.js';
2
2
  export const WEB_SEARCH_TOOL_NAME = 'WebSearch';
3
3
  export function getWebSearchPrompt() {
4
4
  const currentMonthYear = getLocalMonthYear();
5
- return `
6
- - Allows Claude to search the web and use the results to inform responses
7
- - Provides up-to-date information for current events and recent data
8
- - Returns search result information formatted as search result blocks, including links as markdown hyperlinks
9
- - Use this tool for accessing information beyond Claude's knowledge cutoff
10
- - Searches are performed automatically within a single API call
11
-
12
- CRITICAL REQUIREMENT - You MUST follow this:
13
- - After answering the user's question, you MUST include a "Sources:" section at the end of your response
14
- - In the Sources section, list all relevant URLs from the search results as markdown hyperlinks: [Title](URL)
15
- - This is MANDATORY - never skip including sources in your response
16
- - Example format:
17
-
18
- [Your answer here]
19
-
20
- Sources:
21
- - [Source Title 1](https://example.com/1)
22
- - [Source Title 2](https://example.com/2)
23
-
24
- Usage notes:
25
- - Domain filtering is supported to include or block specific websites
26
- - Web search is only available in the US
27
-
28
- IMPORTANT - Use the correct year in search queries:
29
- - The current month is ${currentMonthYear}. You MUST use this year when searching for recent information, documentation, or current events.
30
- - Example: If the user asks for "latest React docs", search for "React documentation" with the current year, NOT last year
5
+ return `
6
+ - Allows Claude to search the web and use the results to inform responses
7
+ - Provides up-to-date information for current events and recent data
8
+ - Returns search result information formatted as search result blocks, including links as markdown hyperlinks
9
+ - Use this tool for accessing information beyond Claude's knowledge cutoff
10
+ - Searches are performed automatically within a single API call
11
+
12
+ CRITICAL REQUIREMENT - You MUST follow this:
13
+ - After answering the user's question, you MUST include a "Sources:" section at the end of your response
14
+ - In the Sources section, list all relevant URLs from the search results as markdown hyperlinks: [Title](URL)
15
+ - This is MANDATORY - never skip including sources in your response
16
+ - Example format:
17
+
18
+ [Your answer here]
19
+
20
+ Sources:
21
+ - [Source Title 1](https://example.com/1)
22
+ - [Source Title 2](https://example.com/2)
23
+
24
+ Usage notes:
25
+ - Domain filtering is supported to include or block specific websites
26
+ - Web search is only available in the US
27
+
28
+ IMPORTANT - Use the correct year in search queries:
29
+ - The current month is ${currentMonthYear}. You MUST use this year when searching for recent information, documentation, or current events.
30
+ - Example: If the user asks for "latest React docs", search for "React documentation" with the current year, NOT last year
31
31
  `;
32
32
  }
@@ -21,6 +21,7 @@
21
21
  * don't interfere with each other.
22
22
  */
23
23
  import { AsyncLocalStorage } from 'async_hooks';
24
+ import { registerAgentContext } from '../core/agents/runtime.js';
24
25
  import { isAgentSwarmsEnabled } from './agentSwarmsEnabled.js';
25
26
  const agentContextStorage = new AsyncLocalStorage();
26
27
  /**
@@ -36,6 +37,7 @@ export function getAgentContext() {
36
37
  * All async operations within the function will have access to this context.
37
38
  */
38
39
  export function runWithAgentContext(context, fn) {
40
+ registerAgentContext(context);
39
41
  return agentContextStorage.run(context, fn);
40
42
  }
41
43
  /**
@@ -9,39 +9,39 @@ import { jsonParse } from './slowOperations.js';
9
9
  const MAX_TRANSCRIPT_CHARS = 2000; // Max chars of transcript per session
10
10
  const MAX_MESSAGES_TO_SCAN = 100; // Max messages to scan from start/end
11
11
  const MAX_SESSIONS_TO_SEARCH = 100; // Max sessions to send to the API
12
- const SESSION_SEARCH_SYSTEM_PROMPT = `Your goal is to find relevant sessions based on a user's search query.
13
-
14
- You will be given a list of sessions with their metadata and a search query. Identify which sessions are most relevant to the query.
15
-
16
- Each session may include:
17
- - Title (display name or custom title)
18
- - Tag (user-assigned category, shown as [tag: name] - users tag sessions with /tag command to categorize them)
19
- - Branch (git branch name, shown as [branch: name])
20
- - Summary (AI-generated summary)
21
- - First message (beginning of the conversation)
22
- - Transcript (excerpt of conversation content)
23
-
24
- IMPORTANT: Tags are user-assigned labels that indicate the session's topic or category. If the query matches a tag exactly or partially, those sessions should be highly prioritized.
25
-
26
- For each session, consider (in order of priority):
27
- 1. Exact tag matches (highest priority - user explicitly categorized this session)
28
- 2. Partial tag matches or tag-related terms
29
- 3. Title matches (custom titles or first message content)
30
- 4. Branch name matches
31
- 5. Summary and transcript content matches
32
- 6. Semantic similarity and related concepts
33
-
34
- CRITICAL: Be VERY inclusive in your matching. Include sessions that:
35
- - Contain the query term anywhere in any field
36
- - Are semantically related to the query (e.g., "testing" matches sessions about "tests", "unit tests", "QA", etc.)
37
- - Discuss topics that could be related to the query
38
- - Have transcripts that mention the concept even in passing
39
-
40
- When in doubt, INCLUDE the session. It's better to return too many results than too few. The user can easily scan through results, but missing relevant sessions is frustrating.
41
-
42
- Return sessions ordered by relevance (most relevant first). If truly no sessions have ANY connection to the query, return an empty array - but this should be rare.
43
-
44
- Respond with ONLY the JSON object, no markdown formatting:
12
+ const SESSION_SEARCH_SYSTEM_PROMPT = `Your goal is to find relevant sessions based on a user's search query.
13
+
14
+ You will be given a list of sessions with their metadata and a search query. Identify which sessions are most relevant to the query.
15
+
16
+ Each session may include:
17
+ - Title (display name or custom title)
18
+ - Tag (user-assigned category, shown as [tag: name] - users tag sessions with /tag command to categorize them)
19
+ - Branch (git branch name, shown as [branch: name])
20
+ - Summary (AI-generated summary)
21
+ - First message (beginning of the conversation)
22
+ - Transcript (excerpt of conversation content)
23
+
24
+ IMPORTANT: Tags are user-assigned labels that indicate the session's topic or category. If the query matches a tag exactly or partially, those sessions should be highly prioritized.
25
+
26
+ For each session, consider (in order of priority):
27
+ 1. Exact tag matches (highest priority - user explicitly categorized this session)
28
+ 2. Partial tag matches or tag-related terms
29
+ 3. Title matches (custom titles or first message content)
30
+ 4. Branch name matches
31
+ 5. Summary and transcript content matches
32
+ 6. Semantic similarity and related concepts
33
+
34
+ CRITICAL: Be VERY inclusive in your matching. Include sessions that:
35
+ - Contain the query term anywhere in any field
36
+ - Are semantically related to the query (e.g., "testing" matches sessions about "tests", "unit tests", "QA", etc.)
37
+ - Discuss topics that could be related to the query
38
+ - Have transcripts that mention the concept even in passing
39
+
40
+ When in doubt, INCLUDE the session. It's better to return too many results than too few. The user can easily scan through results, but missing relevant sessions is frustrating.
41
+
42
+ Return sessions ordered by relevance (most relevant first). If truly no sessions have ANY connection to the query, return an empty array - but this should be rare.
43
+
44
+ Respond with ONLY the JSON object, no markdown formatting:
45
45
  {"relevant_indices": [2, 5, 0]}`;
46
46
  /**
47
47
  * Extracts searchable text content from a message.
@@ -206,11 +206,11 @@ export async function agenticSessionSearch(query, logs, signal) {
206
206
  return parts.join(' ');
207
207
  })
208
208
  .join('\n');
209
- const userMessage = `Sessions:
210
- ${sessionList}
211
-
212
- Search query: "${query}"
213
-
209
+ const userMessage = `Sessions:
210
+ ${sessionList}
211
+
212
+ Search query: "${query}"
213
+
214
214
  Find the sessions that are most relevant to this query.`;
215
215
  // Debug: log first part of the session list
216
216
  logForDebugging(`Agentic search prompt (first 500 chars): ${userMessage.slice(0, 500)}...`);
@@ -83,6 +83,7 @@ function createDefaultGlobalConfig() {
83
83
  todoFeatureEnabled: true,
84
84
  showExpandedTodos: false,
85
85
  messageIdleNotifThresholdMs: 60000,
86
+ awaySummaryBlurDelayMs: 5 * 60_000,
86
87
  autoConnectIde: false,
87
88
  autoInstallIdeExtension: true,
88
89
  fileCheckpointingEnabled: true,
@@ -114,6 +115,7 @@ export const GLOBAL_CONFIG_KEYS = [
114
115
  'todoFeatureEnabled',
115
116
  'showExpandedTodos',
116
117
  'messageIdleNotifThresholdMs',
118
+ 'awaySummaryBlurDelayMs',
117
119
  'autoConnectIde',
118
120
  'autoInstallIdeExtension',
119
121
  'fileCheckpointingEnabled',
@@ -32,16 +32,16 @@ export function isProcessRunning(pid) {
32
32
  export async function getAncestorPidsAsync(pid, maxDepth = 10) {
33
33
  if (process.platform === 'win32') {
34
34
  // For Windows, use a PowerShell script that walks the process tree
35
- const script = `
36
- $pid = ${String(pid)}
37
- $ancestors = @()
38
- for ($i = 0; $i -lt ${maxDepth}; $i++) {
39
- $proc = Get-CimInstance Win32_Process -Filter "ProcessId=$pid" -ErrorAction SilentlyContinue
40
- if (-not $proc -or -not $proc.ParentProcessId -or $proc.ParentProcessId -eq 0) { break }
41
- $pid = $proc.ParentProcessId
42
- $ancestors += $pid
43
- }
44
- $ancestors -join ','
35
+ const script = `
36
+ $pid = ${String(pid)}
37
+ $ancestors = @()
38
+ for ($i = 0; $i -lt ${maxDepth}; $i++) {
39
+ $proc = Get-CimInstance Win32_Process -Filter "ProcessId=$pid" -ErrorAction SilentlyContinue
40
+ if (-not $proc -or -not $proc.ParentProcessId -or $proc.ParentProcessId -eq 0) { break }
41
+ $pid = $proc.ParentProcessId
42
+ $ancestors += $pid
43
+ }
44
+ $ancestors -join ','
45
45
  `.trim();
46
46
  const result = await execFileNoThrowWithCwd('powershell.exe', ['-NoProfile', '-Command', script], { timeout: 3000 });
47
47
  if (result.code !== 0 || !result.stdout?.trim()) {
@@ -98,17 +98,17 @@ export function getProcessCommand(pid) {
98
98
  export async function getAncestorCommandsAsync(pid, maxDepth = 10) {
99
99
  if (process.platform === 'win32') {
100
100
  // For Windows, use a PowerShell script that walks the process tree and collects commands
101
- const script = `
102
- $currentPid = ${String(pid)}
103
- $commands = @()
104
- for ($i = 0; $i -lt ${maxDepth}; $i++) {
105
- $proc = Get-CimInstance Win32_Process -Filter "ProcessId=$currentPid" -ErrorAction SilentlyContinue
106
- if (-not $proc) { break }
107
- if ($proc.CommandLine) { $commands += $proc.CommandLine }
108
- if (-not $proc.ParentProcessId -or $proc.ParentProcessId -eq 0) { break }
109
- $currentPid = $proc.ParentProcessId
110
- }
111
- $commands -join [char]0
101
+ const script = `
102
+ $currentPid = ${String(pid)}
103
+ $commands = @()
104
+ for ($i = 0; $i -lt ${maxDepth}; $i++) {
105
+ $proc = Get-CimInstance Win32_Process -Filter "ProcessId=$currentPid" -ErrorAction SilentlyContinue
106
+ if (-not $proc) { break }
107
+ if ($proc.CommandLine) { $commands += $proc.CommandLine }
108
+ if (-not $proc.ParentProcessId -or $proc.ParentProcessId -eq 0) { break }
109
+ $currentPid = $proc.ParentProcessId
110
+ }
111
+ $commands -join [char]0
112
112
  `.trim();
113
113
  const result = await execFileNoThrowWithCwd('powershell.exe', ['-NoProfile', '-Command', script], { timeout: 3000 });
114
114
  if (result.code !== 0 || !result.stdout?.trim()) {
@@ -137,10 +137,10 @@ export async function performHeapDump(trigger = 'manual', dumpNumber = 0) {
137
137
  // the heap dump itself allocates memory and would skew the numbers.
138
138
  const diagnostics = await captureMemoryDiagnostics(trigger, dumpNumber);
139
139
  const toGB = (bytes) => (bytes / 1024 / 1024 / 1024).toFixed(3);
140
- logForDebugging(`[HeapDump] Memory state:
141
- heapUsed: ${toGB(diagnostics.memoryUsage.heapUsed)} GB (in snapshot)
142
- external: ${toGB(diagnostics.memoryUsage.external)} GB (NOT in snapshot)
143
- rss: ${toGB(diagnostics.memoryUsage.rss)} GB (total process)
140
+ logForDebugging(`[HeapDump] Memory state:
141
+ heapUsed: ${toGB(diagnostics.memoryUsage.heapUsed)} GB (in snapshot)
142
+ external: ${toGB(diagnostics.memoryUsage.external)} GB (NOT in snapshot)
143
+ rss: ${toGB(diagnostics.memoryUsage.rss)} GB (total process)
144
144
  ${diagnostics.analysis.recommendation}`);
145
145
  const dumpDir = getDesktopPath();
146
146
  await getFsImplementation().mkdir(dumpDir);
@@ -57,8 +57,8 @@ function getMaxMcpOutputChars() {
57
57
  return getMaxMcpOutputTokens() * 4;
58
58
  }
59
59
  function getTruncationMessage() {
60
- return `\n\n[OUTPUT TRUNCATED - exceeded ${getMaxMcpOutputTokens()} token limit]
61
-
60
+ return `\n\n[OUTPUT TRUNCATED - exceeded ${getMaxMcpOutputTokens()} token limit]
61
+
62
62
  The tool output was truncated. If this MCP server provides pagination or filtering tools, use them to retrieve specific portions of the data. If pagination is not available, inform the user that you are working with truncated output and results may be incomplete.`;
63
63
  }
64
64
  function truncateString(content, maxChars) {
@@ -144,5 +144,5 @@ export async function ensureModelStringsInitialized() {
144
144
  }
145
145
  export function resetModelStringsForProviderChange() {
146
146
  clearModelStrings();
147
- updateBedrockModelStrings.cache.clear?.();
147
+ updateBedrockModelStrings.cache?.clear?.();
148
148
  }
@@ -74,6 +74,11 @@ export function isOllamaProviderConfigured() {
74
74
  }
75
75
  }
76
76
  export function isOllamaCloudProviderConfigured() {
77
+ // Si Ollama local ya esta operativo, tratamos ollama-cloud como listo.
78
+ // Esto permite usar modelos cloud con la autenticacion/sesion local de Ollama.
79
+ if (isOllamaProviderConfigured()) {
80
+ return true;
81
+ }
77
82
  try {
78
83
  const storage = getSecureStorage().read();
79
84
  const scopedKeys = Object.entries(storage?.providerProfileApiKeys ?? {}).some(([key, value]) => key.startsWith('ollama-cloud/') &&
@@ -71,9 +71,9 @@ export async function listProviderAgents(filters) {
71
71
  }
72
72
  const where = clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : '';
73
73
  return db
74
- .prepare(`SELECT id, workspace_id, profile_id, name, role_kind, system_prompt, model_override, tool_policy, autonomy_level, is_orchestrator, is_enabled, created_at, updated_at
75
- FROM provider_agents
76
- ${where}
74
+ .prepare(`SELECT id, workspace_id, profile_id, name, role_kind, system_prompt, model_override, tool_policy, autonomy_level, is_orchestrator, is_enabled, created_at, updated_at
75
+ FROM provider_agents
76
+ ${where}
77
77
  ORDER BY workspace_id, name, created_at, id`)
78
78
  .all(...params)
79
79
  .map(rowToAgent)
@@ -82,8 +82,8 @@ export async function listProviderAgents(filters) {
82
82
  export async function getProviderAgentById(id) {
83
83
  const db = await getOrchestrationDatabase();
84
84
  const row = db
85
- .prepare(`SELECT id, workspace_id, profile_id, name, role_kind, system_prompt, model_override, tool_policy, autonomy_level, is_orchestrator, is_enabled, created_at, updated_at
86
- FROM provider_agents
85
+ .prepare(`SELECT id, workspace_id, profile_id, name, role_kind, system_prompt, model_override, tool_policy, autonomy_level, is_orchestrator, is_enabled, created_at, updated_at
86
+ FROM provider_agents
87
87
  WHERE id = ?`)
88
88
  .get(id);
89
89
  return rowToAgent(row);
@@ -91,8 +91,8 @@ export async function getProviderAgentById(id) {
91
91
  export async function getProviderAgentByWorkspaceAndName(workspaceId, name) {
92
92
  const db = await getOrchestrationDatabase();
93
93
  const row = db
94
- .prepare(`SELECT id, workspace_id, profile_id, name, role_kind, system_prompt, model_override, tool_policy, autonomy_level, is_orchestrator, is_enabled, created_at, updated_at
95
- FROM provider_agents
94
+ .prepare(`SELECT id, workspace_id, profile_id, name, role_kind, system_prompt, model_override, tool_policy, autonomy_level, is_orchestrator, is_enabled, created_at, updated_at
95
+ FROM provider_agents
96
96
  WHERE workspace_id = ? AND name = ?`)
97
97
  .get(requireText(workspaceId, 'workspaceId'), requireText(name, 'name'));
98
98
  return rowToAgent(row);
@@ -107,8 +107,8 @@ export async function createProviderAgent(input) {
107
107
  const id = randomUUID();
108
108
  const name = requireText(input.name, 'name');
109
109
  const now = nowIso();
110
- db.prepare(`INSERT INTO provider_agents (
111
- id, workspace_id, profile_id, name, role_kind, system_prompt, model_override, tool_policy, autonomy_level, is_orchestrator, is_enabled, created_at, updated_at
110
+ db.prepare(`INSERT INTO provider_agents (
111
+ id, workspace_id, profile_id, name, role_kind, system_prompt, model_override, tool_policy, autonomy_level, is_orchestrator, is_enabled, created_at, updated_at
112
112
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, requireText(input.workspaceId, 'workspaceId'), requireText(input.profileId, 'profileId'), name, toNullableText(input.roleKind), toNullableText(input.systemPrompt), toNullableText(input.modelOverride), toNullableText(input.toolPolicy), toNullableText(input.autonomyLevel), toDbBoolean(input.isOrchestrator ?? false), toDbBoolean(resolveBoolean(input.isEnabled, true)), now, now);
113
113
  const created = await getProviderAgentById(id);
114
114
  if (!created) {
@@ -140,8 +140,8 @@ export async function updateProviderAgent(id, input) {
140
140
  : toNullableText(input.autonomyLevel);
141
141
  const isOrchestrator = resolveBoolean(input.isOrchestrator, existing.isOrchestrator);
142
142
  const isEnabled = resolveBoolean(input.isEnabled, existing.isEnabled);
143
- db.prepare(`UPDATE provider_agents
144
- SET name = ?, role_kind = ?, system_prompt = ?, model_override = ?, tool_policy = ?, autonomy_level = ?, is_orchestrator = ?, is_enabled = ?, updated_at = ?
143
+ db.prepare(`UPDATE provider_agents
144
+ SET name = ?, role_kind = ?, system_prompt = ?, model_override = ?, tool_policy = ?, autonomy_level = ?, is_orchestrator = ?, is_enabled = ?, updated_at = ?
145
145
  WHERE id = ?`).run(name, roleKind, systemPrompt, modelOverride, toolPolicy, autonomyLevel, toDbBoolean(isOrchestrator), toDbBoolean(isEnabled), nowIso(), id);
146
146
  const updated = await getProviderAgentById(id);
147
147
  if (!updated) {
@@ -162,9 +162,9 @@ export async function deleteProviderAgent(id) {
162
162
  export async function listProviderAgentCapabilities(agentId) {
163
163
  const db = await getOrchestrationDatabase();
164
164
  return db
165
- .prepare(`SELECT id, agent_id, capability, weight, created_at, updated_at
166
- FROM provider_agent_capabilities
167
- WHERE agent_id = ?
165
+ .prepare(`SELECT id, agent_id, capability, weight, created_at, updated_at
166
+ FROM provider_agent_capabilities
167
+ WHERE agent_id = ?
168
168
  ORDER BY capability, id`)
169
169
  .all(agentId)
170
170
  .map(rowToCapability)
@@ -173,8 +173,8 @@ export async function listProviderAgentCapabilities(agentId) {
173
173
  export async function getProviderAgentCapabilityById(id) {
174
174
  const db = await getOrchestrationDatabase();
175
175
  const row = db
176
- .prepare(`SELECT id, agent_id, capability, weight, created_at, updated_at
177
- FROM provider_agent_capabilities
176
+ .prepare(`SELECT id, agent_id, capability, weight, created_at, updated_at
177
+ FROM provider_agent_capabilities
178
178
  WHERE id = ?`)
179
179
  .get(id);
180
180
  return rowToCapability(row);
@@ -182,8 +182,8 @@ export async function getProviderAgentCapabilityById(id) {
182
182
  async function getProviderAgentCapabilityByCompositeKey(agentId, capability) {
183
183
  const db = await getOrchestrationDatabase();
184
184
  const row = db
185
- .prepare(`SELECT id, agent_id, capability, weight, created_at, updated_at
186
- FROM provider_agent_capabilities
185
+ .prepare(`SELECT id, agent_id, capability, weight, created_at, updated_at
186
+ FROM provider_agent_capabilities
187
187
  WHERE agent_id = ? AND capability = ?`)
188
188
  .get(agentId, capability);
189
189
  return rowToCapability(row);
@@ -194,8 +194,8 @@ export async function createProviderAgentCapability(input) {
194
194
  const capability = requireText(input.capability, 'capability');
195
195
  const weight = resolveWeight(input.weight);
196
196
  const now = nowIso();
197
- db.prepare(`INSERT INTO provider_agent_capabilities (
198
- id, agent_id, capability, weight, created_at, updated_at
197
+ db.prepare(`INSERT INTO provider_agent_capabilities (
198
+ id, agent_id, capability, weight, created_at, updated_at
199
199
  ) VALUES (?, ?, ?, ?, ?, ?)`).run(id, requireText(input.agentId, 'agentId'), capability, weight, now, now);
200
200
  const created = await getProviderAgentCapabilityById(id);
201
201
  if (!created) {
@@ -223,8 +223,8 @@ export async function updateProviderAgentCapability(id, input) {
223
223
  ? existing.capability
224
224
  : requireText(input.capability, 'capability');
225
225
  const weight = resolveWeight(input.weight, existing.weight);
226
- db.prepare(`UPDATE provider_agent_capabilities
227
- SET capability = ?, weight = ?, updated_at = ?
226
+ db.prepare(`UPDATE provider_agent_capabilities
227
+ SET capability = ?, weight = ?, updated_at = ?
228
228
  WHERE id = ?`).run(capability, weight, nowIso(), id);
229
229
  const updated = await getProviderAgentCapabilityById(id);
230
230
  if (!updated) {
@@ -32,8 +32,8 @@ function resolveDisplayName(provider, displayName) {
32
32
  async function getWorkspaceRowById(id) {
33
33
  const db = await getOrchestrationDatabase();
34
34
  const row = db
35
- .prepare(`SELECT id, provider, display_name, domain_focus, is_enabled, created_at, updated_at
36
- FROM provider_workspaces
35
+ .prepare(`SELECT id, provider, display_name, domain_focus, is_enabled, created_at, updated_at
36
+ FROM provider_workspaces
37
37
  WHERE id = ?`)
38
38
  .get(id);
39
39
  return rowToWorkspace(row);
@@ -41,8 +41,8 @@ async function getWorkspaceRowById(id) {
41
41
  export async function listProviderWorkspaces() {
42
42
  const db = await getOrchestrationDatabase();
43
43
  return db
44
- .prepare(`SELECT id, provider, display_name, domain_focus, is_enabled, created_at, updated_at
45
- FROM provider_workspaces
44
+ .prepare(`SELECT id, provider, display_name, domain_focus, is_enabled, created_at, updated_at
45
+ FROM provider_workspaces
46
46
  ORDER BY provider, created_at, id`)
47
47
  .all()
48
48
  .map(rowToWorkspace)
@@ -54,8 +54,8 @@ export async function getProviderWorkspaceById(id) {
54
54
  export async function getProviderWorkspaceByProvider(provider) {
55
55
  const db = await getOrchestrationDatabase();
56
56
  const row = db
57
- .prepare(`SELECT id, provider, display_name, domain_focus, is_enabled, created_at, updated_at
58
- FROM provider_workspaces
57
+ .prepare(`SELECT id, provider, display_name, domain_focus, is_enabled, created_at, updated_at
58
+ FROM provider_workspaces
59
59
  WHERE provider = ?`)
60
60
  .get(provider);
61
61
  return rowToWorkspace(row);
@@ -66,8 +66,8 @@ async function insertProviderWorkspace(provider, input) {
66
66
  const displayName = resolveDisplayName(provider, input.displayName);
67
67
  const domainFocus = toNullableText(input.domainFocus);
68
68
  const now = nowIso();
69
- db.prepare(`INSERT INTO provider_workspaces (
70
- id, provider, display_name, domain_focus, is_enabled, created_at, updated_at
69
+ db.prepare(`INSERT INTO provider_workspaces (
70
+ id, provider, display_name, domain_focus, is_enabled, created_at, updated_at
71
71
  ) VALUES (?, ?, ?, ?, ?, ?, ?)`).run(id, provider, displayName, domainFocus, toDbBoolean(input.isEnabled ?? true), now, now);
72
72
  const created = await getProviderWorkspaceById(id);
73
73
  if (!created) {
@@ -106,8 +106,8 @@ export async function updateProviderWorkspace(id, input) {
106
106
  ? existing.domainFocus
107
107
  : toNullableText(input.domainFocus);
108
108
  const isEnabled = input.isEnabled === undefined ? existing.isEnabled : input.isEnabled;
109
- db.prepare(`UPDATE provider_workspaces
110
- SET display_name = ?, domain_focus = ?, is_enabled = ?, updated_at = ?
109
+ db.prepare(`UPDATE provider_workspaces
110
+ SET display_name = ?, domain_focus = ?, is_enabled = ?, updated_at = ?
111
111
  WHERE id = ?`).run(displayName, domainFocus, toDbBoolean(isEnabled), nowIso(), id);
112
112
  const updated = await getWorkspaceRowById(id);
113
113
  if (!updated) {