@gajae-code/coding-agent 0.18.10 → 0.18.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 (270) hide show
  1. package/CHANGELOG.md +295 -0
  2. package/dist/types/async/job-manager.d.ts +7 -3
  3. package/dist/types/async/result-formatting.d.ts +2 -0
  4. package/dist/types/autoresearch/git.d.ts +1 -1
  5. package/dist/types/capability/fs.d.ts +2 -2
  6. package/dist/types/cli/accounts-cli.d.ts +2 -2
  7. package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
  8. package/dist/types/cli/install-activation.d.ts +10 -4
  9. package/dist/types/cli/public-command-errors.d.ts +1 -0
  10. package/dist/types/cli/update-cli.d.ts +14 -1
  11. package/dist/types/cli-ordinary.d.ts +2 -2
  12. package/dist/types/commands/accounts.d.ts +2 -1
  13. package/dist/types/commands/migrate.d.ts +1 -1
  14. package/dist/types/commands/sdk.d.ts +5 -0
  15. package/dist/types/commit/changelog/index.d.ts +1 -0
  16. package/dist/types/config/autorouting-tier-map.d.ts +30 -0
  17. package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
  18. package/dist/types/config/config-hot-reload.d.ts +39 -0
  19. package/dist/types/config/file-lock.d.ts +8 -1
  20. package/dist/types/config/model-discovery-manager.d.ts +2 -0
  21. package/dist/types/config/model-profile-activation.d.ts +62 -6
  22. package/dist/types/config/model-registry.d.ts +56 -5
  23. package/dist/types/config/model-resolver.d.ts +2 -0
  24. package/dist/types/config/models-config-schema.d.ts +10 -0
  25. package/dist/types/config/settings-schema.d.ts +46 -3
  26. package/dist/types/config/settings.d.ts +33 -1
  27. package/dist/types/dap/config.d.ts +8 -4
  28. package/dist/types/debug/system-info.d.ts +6 -1
  29. package/dist/types/discovery/mcp-compat.d.ts +3 -1
  30. package/dist/types/edit/modes/patch.d.ts +5 -0
  31. package/dist/types/edit/modes/replace.d.ts +3 -0
  32. package/dist/types/exec/bash-executor.d.ts +12 -0
  33. package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
  34. package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
  35. package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
  36. package/dist/types/migrate/adapters/codex.d.ts +2 -1
  37. package/dist/types/migrate/adapters/index.d.ts +10 -1
  38. package/dist/types/migrate/executor.d.ts +3 -1
  39. package/dist/types/migrate/types.d.ts +15 -3
  40. package/dist/types/modes/components/settings-selector.d.ts +6 -0
  41. package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
  42. package/dist/types/modes/theme/theme.d.ts +1 -0
  43. package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
  44. package/dist/types/runtime-mcp/manager.d.ts +7 -0
  45. package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
  46. package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
  47. package/dist/types/sdk/broker/broker-exit.d.ts +2 -2
  48. package/dist/types/sdk/broker/broker.d.ts +7 -1
  49. package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
  50. package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
  51. package/dist/types/sdk/broker/ensure.d.ts +136 -7
  52. package/dist/types/sdk/broker/hop.d.ts +36 -0
  53. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
  54. package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
  55. package/dist/types/sdk/broker/session-index.d.ts +4 -1
  56. package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
  57. package/dist/types/sdk/bus/index.d.ts +23 -0
  58. package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
  59. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
  60. package/dist/types/sdk/cli/session-cli.d.ts +0 -1
  61. package/dist/types/sdk/host/session-runtime.d.ts +32 -0
  62. package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
  63. package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
  64. package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
  65. package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
  66. package/dist/types/sdk/session-list.d.ts +1 -1
  67. package/dist/types/session/agent-session.d.ts +58 -2
  68. package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
  69. package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
  70. package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
  71. package/dist/types/session/messages.d.ts +5 -1
  72. package/dist/types/session/session-manager.d.ts +13 -3
  73. package/dist/types/session/startup-auth-config.d.ts +24 -2
  74. package/dist/types/session/streaming-output.d.ts +11 -0
  75. package/dist/types/session/terminal-abort.d.ts +3 -1
  76. package/dist/types/session-import/service.d.ts +1 -1
  77. package/dist/types/skill-state/workflow-mutation-guard.d.ts +7 -3
  78. package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
  79. package/dist/types/task/executor.d.ts +19 -2
  80. package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
  81. package/dist/types/tools/atomic-file-write.d.ts +9 -7
  82. package/dist/types/tools/bash-allowed-prefixes.d.ts +11 -0
  83. package/dist/types/tools/descriptors.d.ts +2 -0
  84. package/dist/types/tools/fetch.d.ts +1 -1
  85. package/dist/types/tools/index.d.ts +2 -0
  86. package/dist/types/tools/python.d.ts +1 -1
  87. package/dist/types/tools/report-issue.d.ts +41 -0
  88. package/dist/types/tools/subagent.d.ts +23 -0
  89. package/dist/types/web/scrapers/types.d.ts +8 -1
  90. package/dist/types/web/search/providers/insane.d.ts +7 -1
  91. package/dist/types/web/search/providers/searxng.d.ts +5 -0
  92. package/package.json +8 -8
  93. package/scripts/build-binary.ts +2 -1
  94. package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
  95. package/scripts/generate-docs-index.ts +8 -1
  96. package/scripts/generate-sdk-operation-inventory.ts +22 -4
  97. package/src/async/job-manager.ts +356 -56
  98. package/src/async/result-formatting.ts +40 -0
  99. package/src/autoresearch/git.ts +9 -2
  100. package/src/autoresearch/prompts/prompt-setup.md +1 -1
  101. package/src/capability/fs.ts +27 -19
  102. package/src/capability/index.ts +2 -2
  103. package/src/cli/accounts-cli.ts +176 -8
  104. package/src/cli/auth-broker-cli.ts +21 -11
  105. package/src/cli/doctor/install-repairs.ts +35 -5
  106. package/src/cli/fast-help.ts +1 -1
  107. package/src/cli/install-activation.ts +47 -4
  108. package/src/cli/migrate-cli.ts +7 -5
  109. package/src/cli/public-command-errors.ts +4 -0
  110. package/src/cli/root-flags.ts +2 -2
  111. package/src/cli/stats-cli.ts +9 -5
  112. package/src/cli/update-cli.ts +224 -7
  113. package/src/cli-ordinary.ts +7 -2
  114. package/src/commands/accounts.ts +10 -5
  115. package/src/commands/migrate.ts +3 -3
  116. package/src/commands/sdk.ts +199 -42
  117. package/src/commands/ultragoal.ts +16 -8
  118. package/src/commit/changelog/index.ts +39 -1
  119. package/src/commit/message.ts +10 -3
  120. package/src/config/autorouting-tier-map.ts +30 -0
  121. package/src/config/config-hot-reload-trust.ts +148 -0
  122. package/src/config/config-hot-reload.ts +734 -0
  123. package/src/config/file-lock.ts +216 -56
  124. package/src/config/model-bindings-applier.ts +85 -47
  125. package/src/config/model-discovery-manager.ts +10 -0
  126. package/src/config/model-profile-activation.ts +716 -113
  127. package/src/config/model-registry.ts +1334 -158
  128. package/src/config/model-resolver.ts +3 -1
  129. package/src/config/models-config-schema.ts +6 -0
  130. package/src/config/settings-schema.ts +60 -3
  131. package/src/config/settings.ts +458 -24
  132. package/src/coordinator-mcp/policy.ts +26 -1
  133. package/src/crash/sanitize.ts +4 -0
  134. package/src/customization/import.ts +3 -1
  135. package/src/dap/config.ts +31 -11
  136. package/src/dap/defaults.json +1 -1
  137. package/src/debug/crash-diagnostics.ts +2 -1
  138. package/src/debug/report-bundle.ts +19 -0
  139. package/src/debug/system-info.ts +8 -3
  140. package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
  141. package/src/discovery/agents-md.ts +1 -1
  142. package/src/discovery/helpers.ts +1 -2
  143. package/src/discovery/mcp-compat.ts +120 -17
  144. package/src/edit/apply-patch/index.ts +12 -1
  145. package/src/edit/index.ts +13 -17
  146. package/src/edit/modes/patch.ts +187 -8
  147. package/src/edit/modes/replace.ts +136 -0
  148. package/src/eval/js/context-manager.ts +29 -3
  149. package/src/eval/js/worker-entry.ts +51 -18
  150. package/src/eval/py/executor.ts +14 -4
  151. package/src/eval/py/runner.py +144 -5
  152. package/src/exec/bash-executor.ts +81 -4
  153. package/src/exec/bash-shell-guardian.ts +4 -1
  154. package/src/exec/bash-shell-supervisor.ts +8 -4
  155. package/src/exec/isolated-shell.ts +5 -1
  156. package/src/export/html/index.ts +46 -6
  157. package/src/extensibility/custom-tools/wrapper.ts +3 -1
  158. package/src/extensibility/extensions/loader.ts +8 -1
  159. package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
  160. package/src/gjc-runtime/gc-runtime.ts +33 -6
  161. package/src/gjc-runtime/launch-tmux.ts +7 -2
  162. package/src/gjc-runtime/launch-worktree.test.ts +148 -0
  163. package/src/gjc-runtime/launch-worktree.ts +101 -14
  164. package/src/gjc-runtime/managed-owner-admission.ts +46 -2
  165. package/src/gjc-runtime/session-resolution.ts +38 -6
  166. package/src/gjc-runtime/session-state-lock.ts +59 -14
  167. package/src/gjc-runtime/state-runtime.ts +23 -19
  168. package/src/hooks/native-skill-hook.ts +14 -11
  169. package/src/internal-urls/docs-index.generated.ts +14 -13
  170. package/src/internal-urls/local-protocol.ts +142 -8
  171. package/src/lsp/index.ts +29 -0
  172. package/src/lsp/workspace-path.ts +23 -0
  173. package/src/migrate/action-planner.ts +57 -0
  174. package/src/migrate/adapters/claude-code.ts +23 -4
  175. package/src/migrate/adapters/codex.ts +22 -4
  176. package/src/migrate/adapters/index.ts +22 -4
  177. package/src/migrate/adapters/opencode.ts +6 -1
  178. package/src/migrate/executor.ts +84 -7
  179. package/src/migrate/report.ts +19 -2
  180. package/src/migrate/types.ts +14 -4
  181. package/src/modes/DESIGN.md +51 -0
  182. package/src/modes/acp/permission-mode.ts +18 -1
  183. package/src/modes/components/assistant-message.ts +55 -1
  184. package/src/modes/components/settings-selector.ts +103 -37
  185. package/src/modes/controllers/command-controller.ts +38 -2
  186. package/src/modes/controllers/plan-mode-controller.ts +17 -7
  187. package/src/modes/controllers/selector-controller.ts +62 -6
  188. package/src/modes/interactive-mode.ts +68 -0
  189. package/src/modes/theme/theme.ts +15 -0
  190. package/src/prompts/tools/debug.md +1 -1
  191. package/src/prompts/tools/read.md +1 -1
  192. package/src/prompts/tools/report-issue.md +13 -0
  193. package/src/prompts/tools/task.md +1 -1
  194. package/src/runtime-credential-selector.ts +2 -2
  195. package/src/runtime-mcp/content-limits.ts +7 -0
  196. package/src/runtime-mcp/manager-pool.test.ts +5 -4
  197. package/src/runtime-mcp/manager.ts +32 -0
  198. package/src/runtime-mcp/oauth-flow.ts +32 -6
  199. package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
  200. package/src/runtime-mcp/render.ts +16 -1
  201. package/src/runtime-mcp/tool-bridge.ts +126 -17
  202. package/src/sdk/broker/broker-exit.ts +8 -5
  203. package/src/sdk/broker/broker.ts +342 -82
  204. package/src/sdk/broker/daemon-entry.ts +338 -116
  205. package/src/sdk/broker/doctor-restart.ts +2 -1
  206. package/src/sdk/broker/ensure.ts +1143 -265
  207. package/src/sdk/broker/hop.ts +274 -0
  208. package/src/sdk/broker/lifecycle-ledger.ts +35 -11
  209. package/src/sdk/broker/lock-host-identity.ts +29 -0
  210. package/src/sdk/broker/session-index.ts +62 -12
  211. package/src/sdk/bus/chat-command-policy.ts +16 -3
  212. package/src/sdk/bus/index.ts +52 -21
  213. package/src/sdk/bus/reconciliation-store.ts +201 -8
  214. package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
  215. package/src/sdk/cli/session-cli.ts +21 -6
  216. package/src/sdk/host/session-runtime.test.ts +118 -23
  217. package/src/sdk/host/session-runtime.ts +352 -47
  218. package/src/sdk/lifecycle/service.ts +1 -0
  219. package/src/sdk/prompt-deadline-flush.ts +78 -5
  220. package/src/sdk/prompt-deadline-manager.ts +68 -14
  221. package/src/sdk/protocol/adapter-validation.ts +53 -11
  222. package/src/sdk/protocol/operation-inventory.generated.json +101 -2
  223. package/src/sdk/reconciliation-extensions.ts +1 -0
  224. package/src/sdk/session-list.ts +1 -0
  225. package/src/sdk/session.ts +114 -61
  226. package/src/session/agent-session.ts +1043 -81
  227. package/src/session/internal/managed-session-scope.ts +126 -39
  228. package/src/session/internal/managed-session-storage.ts +14 -11
  229. package/src/session/internal/native-publish-outcome.ts +5 -1
  230. package/src/session/messages.ts +47 -6
  231. package/src/session/session-manager.ts +236 -14
  232. package/src/session/startup-auth-config.ts +116 -8
  233. package/src/session/streaming-output.ts +262 -4
  234. package/src/session/terminal-abort.ts +14 -2
  235. package/src/session-import/service.ts +1 -0
  236. package/src/skill-state/workflow-mutation-guard.ts +491 -32
  237. package/src/slash-commands/builtin-registry.ts +15 -3
  238. package/src/slash-commands/helpers/credential-switch.ts +10 -5
  239. package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
  240. package/src/task/executor.ts +103 -12
  241. package/src/task/index.ts +389 -175
  242. package/src/tools/ast-edit-write-path.ts +64 -0
  243. package/src/tools/ast-edit.ts +18 -1
  244. package/src/tools/atomic-file-write.ts +46 -15
  245. package/src/tools/auto-generated-guard.ts +3 -0
  246. package/src/tools/bash-allowed-prefixes.ts +153 -5
  247. package/src/tools/bash-interactive.ts +14 -2
  248. package/src/tools/bash.ts +14 -0
  249. package/src/tools/debug.ts +7 -6
  250. package/src/tools/descriptors.test.ts +44 -0
  251. package/src/tools/descriptors.ts +34 -2
  252. package/src/tools/fetch.ts +3 -2
  253. package/src/tools/index.ts +2 -0
  254. package/src/tools/output-meta.ts +23 -2
  255. package/src/tools/python.ts +1 -1
  256. package/src/tools/read.ts +17 -35
  257. package/src/tools/report-issue.ts +184 -0
  258. package/src/tools/subagent-render.ts +114 -12
  259. package/src/tools/subagent.ts +108 -1
  260. package/src/tools/todo-write.ts +41 -3
  261. package/src/tools/tool-catalog.generated.ts +31 -3
  262. package/src/tools/write.ts +35 -3
  263. package/src/utils/commit-message-generator.ts +9 -2
  264. package/src/utils/file-mentions.ts +29 -1
  265. package/src/utils/title-generator.ts +7 -2
  266. package/src/web/scrapers/index.ts +3 -1
  267. package/src/web/scrapers/types.ts +8 -0
  268. package/src/web/scrapers/youtube.ts +3 -2
  269. package/src/web/search/providers/insane.ts +91 -28
  270. package/src/web/search/providers/searxng.ts +62 -10
@@ -49,6 +49,7 @@ import {
49
49
  } from "../append-only-mode";
50
50
  import { type AsyncJob, AsyncJobManager, isBackgroundJobSupportEnabled, jobElapsedMs } from "../async";
51
51
  import { asyncJobEndpointId as deriveAsyncJobEndpointId } from "../async/endpoint-id";
52
+ import { formatAsyncResultForFollowUp } from "../async/result-formatting";
52
53
  import { resolveBrowserBackend } from "../browser-backend";
53
54
  import { loadCapability, reset as resetCapabilities } from "../capability";
54
55
  import { type Rule, ruleCapability, setActiveRules } from "../capability/rule";
@@ -161,7 +162,8 @@ import {
161
162
  resolveMCPToolCache,
162
163
  } from "../runtime-mcp";
163
164
  import { createMCPFormInputHandler } from "../runtime-mcp/elicitation";
164
- import type { MCPLoadResult } from "../runtime-mcp/manager";
165
+ import { type MCPLoadResult, omitUnapprovedProjectStdio } from "../runtime-mcp/manager";
166
+ import { omitPluginMcpNameShadows, retainPluginMcpMandatoryNames } from "../runtime-mcp/plugin-mcp-name-filter";
165
167
  import { MCP_STARTUP_WAIT_GRACE_MS } from "../runtime-mcp/startup-policy";
166
168
  import type { MCPServerConfig } from "../runtime-mcp/types";
167
169
  import {
@@ -187,6 +189,7 @@ import {
187
189
  parsePersistedCredentialSelector,
188
190
  resolveStartupAuthConfig,
189
191
  type StartupAuthConfigSnapshot,
192
+ startupAuthConfigError,
190
193
  } from "../session/startup-auth-config";
191
194
  import {
192
195
  isOwnedCompletionEnvelopeAllowed,
@@ -215,6 +218,7 @@ import {
215
218
  computeEssentialBuiltinNames,
216
219
  createTools,
217
220
  HIDDEN_TOOLS,
221
+ type LazyAgentTool,
218
222
  resolveEffectiveDiscoveryMode,
219
223
  type Tool,
220
224
  type ToolSession,
@@ -778,6 +782,7 @@ export async function discoverAuthStorage(
778
782
  const resolvedStartupAuth = startupAuth ?? (await resolveStartupAuthConfig(agentDir));
779
783
  const brokerConfig = resolvedStartupAuth.broker;
780
784
  const credentialRankingMode = resolvedStartupAuth.credentialRankingMode;
785
+ const credentialPreferences = resolvedStartupAuth.credentialPreferences;
781
786
  if (brokerConfig) {
782
787
  const client = new AuthBrokerClient({ url: brokerConfig.url, token: brokerConfig.token });
783
788
  const initialResult = await client.fetchSnapshot();
@@ -789,16 +794,18 @@ export async function discoverAuthStorage(
789
794
  configValueResolver: resolveConfigValue,
790
795
  sourceLabel: `broker ${brokerConfig.url}`,
791
796
  credentialRankingMode,
797
+ credentialPreferences,
792
798
  });
793
- return await reloadDiscoveredAuthStorage(storage);
799
+ return rejectDuplicateCredentialPreferences(await reloadDiscoveredAuthStorage(storage), agentDir);
794
800
  }
795
801
  const dbPath = getAgentDbPath(agentDir);
796
802
  const storage = await AuthStorage.create(dbPath, {
797
803
  configValueResolver: resolveConfigValue,
798
804
  sourceLabel: `local ${dbPath}`,
799
805
  credentialRankingMode,
806
+ credentialPreferences,
800
807
  });
801
- return await reloadDiscoveredAuthStorage(storage);
808
+ return rejectDuplicateCredentialPreferences(await reloadDiscoveredAuthStorage(storage), agentDir);
802
809
  }
803
810
 
804
811
  async function reloadDiscoveredAuthStorage(storage: AuthStorage): Promise<AuthStorage> {
@@ -815,6 +822,26 @@ async function reloadDiscoveredAuthStorage(storage: AuthStorage): Promise<AuthSt
815
822
  return storage;
816
823
  }
817
824
 
825
+ /**
826
+ * Two preference entries can name one stored account through different selectors (`email:` and `account:` for the
827
+ * same login). Only the loaded rows reveal that, so the startup-config check finishes here and fails closed like any
828
+ * other invalid preference list.
829
+ */
830
+ function rejectDuplicateCredentialPreferences(storage: AuthStorage, agentDir: string): AuthStorage {
831
+ const duplicates = storage.findDuplicateCredentialPreferences();
832
+ if (duplicates.length === 0) return storage;
833
+ logger.warn("Configured credential preferences name one account twice", {
834
+ providers: duplicates.map(({ provider }) => sanitizeProviderForLog(provider)),
835
+ });
836
+ const error = startupAuthConfigError(agentDir, "invalid-credential-preferences");
837
+ try {
838
+ storage.close();
839
+ } catch (cleanupError) {
840
+ throw attachStartupCleanupDiagnostic(error, cleanupError);
841
+ }
842
+ throw error;
843
+ }
844
+
818
845
  /** Ranking is resolved as part of the typed startup-auth snapshot. */
819
846
 
820
847
  /**
@@ -1309,8 +1336,11 @@ function classifyInheritedMcpToolNames(
1309
1336
  for (const tool of tools) {
1310
1337
  const serverName = tool.mcpServerName;
1311
1338
  if (serverName === undefined) continue;
1312
- if (pluginServers?.has(serverName)) pluginMcpToolNames.push(tool.name);
1313
- else if (conventionalServers?.has(serverName)) conventionalMcpToolNames.push(tool.name);
1339
+ // Caller-supplied source metadata is descriptive; only a manager's
1340
+ // validated plugin-server set can grant mandatory-tool authority.
1341
+ if (pluginServers?.has(serverName)) {
1342
+ pluginMcpToolNames.push(tool.name);
1343
+ } else if (conventionalServers?.has(serverName)) conventionalMcpToolNames.push(tool.name);
1314
1344
  }
1315
1345
  return { pluginMcpToolNames, conventionalMcpToolNames };
1316
1346
  }
@@ -1549,6 +1579,19 @@ function validateAutomationTools(options: CreateAgentSessionOptions): Automation
1549
1579
  return automationTools;
1550
1580
  }
1551
1581
 
1582
+ /** User/global `mcp.enableProjectConfig` only. A project file cannot set it.
1583
+ * Unset keeps non-stdio project MCP and does not approve a project stdio spawn.
1584
+ */
1585
+ function nativeProjectMcpAutoload(settings: Settings): {
1586
+ enableProjectConfig: boolean;
1587
+ allowProjectStdio: boolean;
1588
+ } {
1589
+ const configured = settings.getGlobal("mcp.enableProjectConfig");
1590
+ if (configured === true) return { enableProjectConfig: true, allowProjectStdio: true };
1591
+ if (configured === false) return { enableProjectConfig: false, allowProjectStdio: false };
1592
+ return { enableProjectConfig: true, allowProjectStdio: false };
1593
+ }
1594
+
1552
1595
  export async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {
1553
1596
  const automationTools = validateAutomationTools(options);
1554
1597
  const primaryControlSurface = primaryControlSurfaceFor(options);
@@ -2515,33 +2558,6 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2515
2558
 
2516
2559
  const backgroundJobsEnabled = isBackgroundJobSupportEnabled(settings);
2517
2560
  const asyncMaxJobs = Math.min(100, Math.max(1, settings.get("async.maxJobs") ?? 100));
2518
- const ASYNC_INLINE_RESULT_MAX_CHARS = 12_000;
2519
- const ASYNC_PREVIEW_MAX_CHARS = 4_000;
2520
- const formatAsyncResultForFollowUp = async (result: string, allowArtifact = true): Promise<string> => {
2521
- if (result.length <= ASYNC_INLINE_RESULT_MAX_CHARS) {
2522
- return result;
2523
- }
2524
-
2525
- const preview = `${result.slice(0, ASYNC_PREVIEW_MAX_CHARS)}\n\n[Output truncated. Showing first ${ASYNC_PREVIEW_MAX_CHARS.toLocaleString()} characters.]`;
2526
- // A delivery already denied by a scope:"owned" gate never reaches the
2527
- // model: allocating an artifact for it would leave the stopped job's
2528
- // output in an unreferenced artifact after the flush drops it (review
2529
- // thread P2). Only the inline preview is produced.
2530
- if (!allowArtifact) return preview;
2531
- try {
2532
- const { path: artifactPath, id: artifactId } = await sessionManager.allocateArtifactPath("async");
2533
- if (artifactPath && artifactId) {
2534
- await Bun.write(artifactPath, result);
2535
- return `${preview}\nFull output: artifact://${artifactId}`;
2536
- }
2537
- } catch (error) {
2538
- logger.warn("Failed to persist async follow-up artifact", {
2539
- error: error instanceof Error ? error.message : String(error),
2540
- });
2541
- }
2542
-
2543
- return preview;
2544
- };
2545
2561
  // Only top-level sessions own an AsyncJobManager. Subagents reach the
2546
2562
  // parent's manager via `AsyncJobManager.instance()` (set below), so creating
2547
2563
  // a second instance here just to leave it orphaned wastes a constructor and
@@ -2599,7 +2615,11 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2599
2615
  if (job) asyncJobManager?.retainParkedDelivery(job, result);
2600
2616
  return;
2601
2617
  }
2602
- const formattedResult = await formatAsyncResultForFollowUp(result, !deniedOwnedDelivery);
2618
+ const formattedResult = await formatAsyncResultForFollowUp(
2619
+ sessionManager,
2620
+ result,
2621
+ !deniedOwnedDelivery,
2622
+ );
2603
2623
  if (
2604
2624
  foldDisposition.kind === "receipt" &&
2605
2625
  job &&
@@ -2742,16 +2762,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2742
2762
  ownedMcpManagerTools = [];
2743
2763
  publishOwnedMcpTools = false;
2744
2764
  let nextManager: MCPManager | undefined;
2765
+ const projectMcp = nativeProjectMcpAutoload(settings);
2745
2766
  try {
2746
2767
  const loaded = await loadAllMCPConfigs(to, {
2747
2768
  agentDir,
2748
- enableProjectConfig: settings.has("mcp.enableProjectConfig")
2749
- ? settings.get("mcp.enableProjectConfig")
2750
- : true,
2769
+ enableProjectConfig: projectMcp.enableProjectConfig,
2751
2770
  autoloadOnly: true,
2752
2771
  nativeOnly: true,
2753
2772
  settings,
2754
2773
  });
2774
+ omitUnapprovedProjectStdio(loaded.configs, loaded.sources, projectMcp.allowProjectStdio);
2755
2775
  const { configs: pluginConfigs } = await buildPluginMcpConfigs({ cwd: to });
2756
2776
  const pluginNames = new Set(Object.keys(pluginConfigs));
2757
2777
  const mergedConfigs = { ...loaded.configs, ...pluginConfigs };
@@ -2776,6 +2796,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2776
2796
  {
2777
2797
  sharedPoolIdleMs: settings.get("mcp.sharedPoolIdleMs"),
2778
2798
  toolCacheServerNames: conventionalCacheServerNames,
2799
+ allowUntrustedProjectStdio: projectMcp.allowProjectStdio,
2779
2800
  },
2780
2801
  );
2781
2802
  nextManager.setAuthStorage(authStorage);
@@ -2814,9 +2835,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2814
2835
  for (const tool of result.tools) {
2815
2836
  const serverName = tool.mcpServerName;
2816
2837
  if (serverName === undefined) continue;
2817
- if (pluginNames.has(serverName)) pluginMcpToolNames.push(tool.name);
2818
- else conventionalMcpToolNames.push(tool.name);
2838
+ if (!pluginNames.has(serverName)) conventionalMcpToolNames.push(tool.name);
2819
2839
  }
2840
+ pluginMcpToolNames.push(
2841
+ ...retainPluginMcpMandatoryNames(
2842
+ result.tools,
2843
+ result.tools
2844
+ .filter(tool => tool.mcpServerName && pluginNames.has(tool.mcpServerName))
2845
+ .map(tool => tool.name),
2846
+ ),
2847
+ );
2820
2848
  }
2821
2849
  } catch (error) {
2822
2850
  logger.warn("Failed to recreate MCP authority after session rescope", {
@@ -3281,6 +3309,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
3281
3309
  getWorkflowGateEmitter: () => session?.getWorkflowGateEmitter(),
3282
3310
  getAskAnswerSource: () => session?.getAskAnswerSource(),
3283
3311
  getGoalRuntime: () => session?.goalRuntime,
3312
+ getSdkPermissionMode: () => session?.sdkPermissionMode ?? "allow",
3284
3313
  getClientBridge: () => session?.clientBridge,
3285
3314
  getCompactContext: () => session.formatCompactContext(),
3286
3315
  getTodoPhases: () => session.getTodoPhases(),
@@ -3400,6 +3429,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
3400
3429
  options.toolNames,
3401
3430
  automationTools,
3402
3431
  );
3432
+ const taskFacade = builtinTools.find(tool => tool.name === "task") as LazyAgentTool | undefined;
3403
3433
 
3404
3434
  // A top-level session loads MCP tools from three bounded surfaces: a
3405
3435
  // caller-supplied exact config (`--mcp-config`), conventional native
@@ -3754,6 +3784,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
3754
3784
  // `--mcp-config` exact-file sessions never reach here. The owned manager's
3755
3785
  // tools are surfaced as always-on custom tools (like plugin MCPs), so an
3756
3786
  // ordinary session exposes them without needing MCP discovery mode.
3787
+ const projectMcp = nativeProjectMcpAutoload(settings);
3757
3788
  let conventionalConfigs: Record<string, MCPServerConfig> = {};
3758
3789
  let conventionalSources: Record<string, SourceMeta> = {};
3759
3790
  if (options.enableMcpAutoload !== false) {
@@ -3763,13 +3794,10 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
3763
3794
  // `gjc mcp add` (user scope) writes; an SDK embedder that runs on
3764
3795
  // its own agent directory autoloads its own registrations.
3765
3796
  agentDir,
3766
- // Project-scope native config loads by default; only an
3767
- // explicitly configured `mcp.enableProjectConfig: false`
3768
- // disables it (the legacy schema default stays false for
3769
- // foreign-format discovery consumers of the capability system).
3770
- enableProjectConfig: settings.has("mcp.enableProjectConfig")
3771
- ? settings.get("mcp.enableProjectConfig")
3772
- : true,
3797
+ // Non-stdio project MCP stays on unless the user/global layer
3798
+ // sets `mcp.enableProjectConfig` to false. Project files cannot
3799
+ // set that flag. Project stdio also needs it explicitly true.
3800
+ enableProjectConfig: projectMcp.enableProjectConfig,
3773
3801
  autoloadOnly: true,
3774
3802
  // Runtime authority is GJC's native `.gjc` config in both scopes;
3775
3803
  // Claude Code/Codex MCP files are explicit import sources into
@@ -3777,6 +3805,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
3777
3805
  nativeOnly: true,
3778
3806
  settings,
3779
3807
  });
3808
+ omitUnapprovedProjectStdio(loaded.configs, loaded.sources, projectMcp.allowProjectStdio);
3780
3809
  conventionalConfigs = loaded.configs;
3781
3810
  conventionalSources = loaded.sources;
3782
3811
  for (const warning of loaded.warnings) {
@@ -3841,6 +3870,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
3841
3870
  {
3842
3871
  sharedPoolIdleMs: settings.get("mcp.sharedPoolIdleMs"),
3843
3872
  toolCacheServerNames: conventionalCacheServerNames,
3873
+ allowUntrustedProjectStdio: projectMcp.allowProjectStdio,
3844
3874
  ...(maxPluginMcpStartupWaitMs === undefined
3845
3875
  ? {}
3846
3876
  : { maxStartupTimeoutMs: maxPluginMcpStartupWaitMs }),
@@ -3940,7 +3970,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
3940
3970
  const inlineExtensions: ExtensionFactory[] = [...(options.extensions ?? [])];
3941
3971
  const discoveredHookExtensions: Array<{ factory: ExtensionFactory; name: string }> = [];
3942
3972
  if (customTools.length > 0) {
3943
- inlineExtensions.push(createCustomToolsExtension(customTools));
3973
+ inlineExtensions.push(createCustomToolsExtension(omitPluginMcpNameShadows(customTools)));
3944
3974
  }
3945
3975
  if (!options.disableExtensionDiscovery) {
3946
3976
  try {
@@ -4198,18 +4228,19 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
4198
4228
  });
4199
4229
  }
4200
4230
 
4201
- // Extension modules are discovered at session startup from the canonical
4202
- // native locations (`<agentDir>/extensions`, `<cwd>/.gjc/extensions`),
4203
- // installed plugin bundles, the `extensions` setting, and explicitly
4204
- // supplied `additionalExtensionPaths`. `disableExtensionDiscovery` keeps its
4205
- // documented opt-out semantics: explicit paths still load, matching
4231
+ // Extension modules are discovered at session startup from the user agent
4232
+ // directory, installed plugin bundles, the user/global `extensions` setting,
4233
+ // and explicitly supplied `additionalExtensionPaths`. A repository
4234
+ // `.gjc/extensions` tree is not imported. `disableExtensionDiscovery` keeps
4235
+ // its documented opt-out semantics: explicit paths still load, matching
4206
4236
  // `cli/list-models.ts`. A caller-supplied `preloadedExtensions` result
4207
4237
  // suppresses discovery entirely.
4208
4238
  const explicitExtensionPaths = options.additionalExtensionPaths ?? [];
4209
- // The `extensions` setting is schema-typed as an array of paths, but a
4210
- // hand-edited config can hold an invalid shape; discovery must degrade to
4211
- // no extra paths instead of aborting startup for every session.
4212
- const extensionsSettingPaths = Array.isArray(settings.get("extensions")) ? settings.get("extensions") : [];
4239
+ // The merged `extensions` value includes the project layer, which can name
4240
+ // any module. Only the user/global list is imported. A hand-edited value
4241
+ // with an invalid shape contributes no extra paths.
4242
+ const globalExtensionPaths = settings.getGlobal("extensions");
4243
+ const extensionsSettingPaths = Array.isArray(globalExtensionPaths) ? globalExtensionPaths : [];
4213
4244
  // Discovery must never block session creation: a filesystem or plugin-registry
4214
4245
  // failure degrades to the explicit paths and then to no extensions at all, and
4215
4246
  // the failure stays observable in `extensionsResult.errors`.
@@ -4919,6 +4950,13 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
4919
4950
  }
4920
4951
  }
4921
4952
  }
4953
+ // Mandatory names follow the plugin tools that survived registration.
4954
+ // A colliding user tool keeps the normalized name and must stay selectable.
4955
+ pluginMcpToolNames.splice(
4956
+ 0,
4957
+ pluginMcpToolNames.length,
4958
+ ...retainPluginMcpMandatoryNames(customTools, pluginMcpToolNames),
4959
+ );
4922
4960
  const mandatoryMCPToolNameSet = new Set(pluginMcpToolNames);
4923
4961
  const selectableExplicitMCPToolNames = explicitlyRequestedMCPToolNames.filter(
4924
4962
  name => !mandatoryMCPToolNameSet.has(name),
@@ -5497,6 +5535,12 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
5497
5535
  // carried by the host replay ring through the internal runtime seam above.
5498
5536
  if (autoroutingInactive) session.configWarnings.push(AUTOROUTING_INACTIVE_WARNING);
5499
5537
  hasSession = true;
5538
+ if (taskFacade) {
5539
+ const unregisterTaskMoveListener = sessionManager.registerAfterMoveListener(move =>
5540
+ taskFacade.invalidateForSessionMove(move.newCwd),
5541
+ );
5542
+ session.registerToolSessionCleanup(unregisterTaskMoveListener);
5543
+ }
5500
5544
  const cleanupOwnedManager = cleanupOwnedMcpManager;
5501
5545
  const sessionOwnedMcpManager = ownsMcpManager ? mcpManager : undefined;
5502
5546
  if (cleanupOwnedManager && cleanupOwnedMcpManagerOwner !== sessionOwnedMcpManager) {
@@ -5745,14 +5789,19 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
5745
5789
  const previousNames = ownedMcpManagerToolNames;
5746
5790
  const nextToolNames = nextTools.map(tool => tool.name);
5747
5791
  const previousSet = new Set(previousNames);
5748
- const nextPluginToolNames = nextTools
5749
- .filter(tool => tool.mcpServerName && pluginServerNames.has(tool.mcpServerName))
5750
- .map(tool => tool.name);
5792
+ const nextPluginToolNames = retainPluginMcpMandatoryNames(
5793
+ nextTools,
5794
+ nextTools
5795
+ .filter(tool => tool.mcpServerName && pluginServerNames.has(tool.mcpServerName))
5796
+ .map(tool => tool.name),
5797
+ );
5751
5798
  const nextConventionalToolNames = nextTools
5752
5799
  .filter(tool => tool.mcpServerName && conventionalServerNames.has(tool.mcpServerName))
5753
5800
  .map(tool => tool.name);
5754
5801
  const nextMandatoryMcpToolNames = [
5755
- ...pluginMcpToolNames.filter(name => !previousSet.has(name)),
5802
+ ...retainPluginMcpMandatoryNames(nextTools, pluginMcpToolNames).filter(
5803
+ name => !previousSet.has(name),
5804
+ ),
5756
5805
  ...nextPluginToolNames,
5757
5806
  ];
5758
5807
  const nextConventionalMcpToolNames = [
@@ -5865,9 +5914,13 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
5865
5914
  const previousNames = inheritedMcpManagerToolNames;
5866
5915
  const nextNames = snapshot.map(tool => tool.name);
5867
5916
  const classifiedTools = classifyInheritedMcpToolNames(manager, snapshot);
5917
+ const mandatoryPluginToolNames = retainPluginMcpMandatoryNames(
5918
+ snapshot,
5919
+ classifiedTools.pluginMcpToolNames,
5920
+ );
5868
5921
  try {
5869
5922
  await session.replaceNamedCustomTools(previousNames, snapshot, {
5870
- mandatoryMCPToolNames: classifiedTools.pluginMcpToolNames,
5923
+ mandatoryMCPToolNames: mandatoryPluginToolNames,
5871
5924
  activateNewTools: false,
5872
5925
  });
5873
5926
  } catch (error) {
@@ -5875,7 +5928,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
5875
5928
  throw error;
5876
5929
  }
5877
5930
  inheritedMcpManagerToolNames = nextNames;
5878
- pluginMcpToolNames.splice(0, pluginMcpToolNames.length, ...classifiedTools.pluginMcpToolNames);
5931
+ pluginMcpToolNames.splice(0, pluginMcpToolNames.length, ...mandatoryPluginToolNames);
5879
5932
  conventionalMcpToolNames.splice(
5880
5933
  0,
5881
5934
  conventionalMcpToolNames.length,