actoviq-agent-sdk 0.4.12 → 0.4.13

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 (194) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/src/config/agentDefinitionMigration.d.ts +125 -0
  3. package/dist/src/config/agentDefinitionMigration.d.ts.map +1 -0
  4. package/dist/src/config/agentDefinitionMigration.js +540 -0
  5. package/dist/src/config/agentDefinitionMigration.js.map +1 -0
  6. package/dist/src/config/agentProfiles.d.ts +19 -0
  7. package/dist/src/config/agentProfiles.d.ts.map +1 -1
  8. package/dist/src/config/agentProfiles.js +65 -13
  9. package/dist/src/config/agentProfiles.js.map +1 -1
  10. package/dist/src/config/modelConfigurationCatalog.d.ts +25 -0
  11. package/dist/src/config/modelConfigurationCatalog.d.ts.map +1 -0
  12. package/dist/src/config/modelConfigurationCatalog.js +50 -0
  13. package/dist/src/config/modelConfigurationCatalog.js.map +1 -0
  14. package/dist/src/gui/agentTargetPicker.d.ts +32 -0
  15. package/dist/src/gui/agentTargetPicker.d.ts.map +1 -0
  16. package/dist/src/gui/agentTargetPicker.js +99 -0
  17. package/dist/src/gui/agentTargetPicker.js.map +1 -0
  18. package/dist/src/gui/electronMain.js +1 -0
  19. package/dist/src/gui/electronMain.js.map +1 -1
  20. package/dist/src/gui/hadamardGui.d.ts +23 -0
  21. package/dist/src/gui/hadamardGui.d.ts.map +1 -1
  22. package/dist/src/gui/hadamardGui.js +4120 -931
  23. package/dist/src/gui/hadamardGui.js.map +1 -1
  24. package/dist/src/gui/projectWorkbench.d.ts +6 -2
  25. package/dist/src/gui/projectWorkbench.d.ts.map +1 -1
  26. package/dist/src/gui/projectWorkbench.js +76 -67
  27. package/dist/src/gui/projectWorkbench.js.map +1 -1
  28. package/dist/src/gui/promptTemplates.d.ts +0 -1
  29. package/dist/src/gui/promptTemplates.d.ts.map +1 -1
  30. package/dist/src/gui/promptTemplates.js +0 -3
  31. package/dist/src/gui/promptTemplates.js.map +1 -1
  32. package/dist/src/gui/transcript/clientBundle.d.ts +6 -1
  33. package/dist/src/gui/transcript/clientBundle.d.ts.map +1 -1
  34. package/dist/src/gui/transcript/clientBundle.js +6 -1
  35. package/dist/src/gui/transcript/clientBundle.js.map +1 -1
  36. package/dist/src/help/productCapabilities.d.ts +17 -0
  37. package/dist/src/help/productCapabilities.d.ts.map +1 -0
  38. package/dist/src/help/productCapabilities.js +146 -0
  39. package/dist/src/help/productCapabilities.js.map +1 -0
  40. package/dist/src/index.d.ts +15 -4
  41. package/dist/src/index.d.ts.map +1 -1
  42. package/dist/src/index.js +9 -3
  43. package/dist/src/index.js.map +1 -1
  44. package/dist/src/issues/issueExecution.d.ts.map +1 -1
  45. package/dist/src/issues/issueExecution.js +29 -9
  46. package/dist/src/issues/issueExecution.js.map +1 -1
  47. package/dist/src/manager/assistantGlobalTools.d.ts +44 -0
  48. package/dist/src/manager/assistantGlobalTools.d.ts.map +1 -1
  49. package/dist/src/manager/assistantGlobalTools.js +565 -32
  50. package/dist/src/manager/assistantGlobalTools.js.map +1 -1
  51. package/dist/src/manager/assistantProposals.d.ts +87 -0
  52. package/dist/src/manager/assistantProposals.d.ts.map +1 -0
  53. package/dist/src/manager/assistantProposals.js +207 -0
  54. package/dist/src/manager/assistantProposals.js.map +1 -0
  55. package/dist/src/manager/referenceIndex.d.ts +82 -0
  56. package/dist/src/manager/referenceIndex.d.ts.map +1 -0
  57. package/dist/src/manager/referenceIndex.js +167 -0
  58. package/dist/src/manager/referenceIndex.js.map +1 -0
  59. package/dist/src/manager/referenceOperations.d.ts +108 -0
  60. package/dist/src/manager/referenceOperations.d.ts.map +1 -0
  61. package/dist/src/manager/referenceOperations.js +821 -0
  62. package/dist/src/manager/referenceOperations.js.map +1 -0
  63. package/dist/src/manager/resolveTargetRef.d.ts +67 -0
  64. package/dist/src/manager/resolveTargetRef.d.ts.map +1 -0
  65. package/dist/src/manager/resolveTargetRef.js +81 -0
  66. package/dist/src/manager/resolveTargetRef.js.map +1 -0
  67. package/dist/src/router/modelRouter.d.ts +22 -2
  68. package/dist/src/router/modelRouter.d.ts.map +1 -1
  69. package/dist/src/router/modelRouter.js +76 -9
  70. package/dist/src/router/modelRouter.js.map +1 -1
  71. package/dist/src/runtime/agentClient.d.ts +18 -0
  72. package/dist/src/runtime/agentClient.d.ts.map +1 -1
  73. package/dist/src/runtime/agentClient.js +209 -21
  74. package/dist/src/runtime/agentClient.js.map +1 -1
  75. package/dist/src/runtime/agentSession.d.ts +7 -0
  76. package/dist/src/runtime/agentSession.d.ts.map +1 -1
  77. package/dist/src/runtime/agentSession.js +10 -0
  78. package/dist/src/runtime/agentSession.js.map +1 -1
  79. package/dist/src/runtime/agentTemplates.d.ts +28 -0
  80. package/dist/src/runtime/agentTemplates.d.ts.map +1 -0
  81. package/dist/src/runtime/agentTemplates.js +73 -0
  82. package/dist/src/runtime/agentTemplates.js.map +1 -0
  83. package/dist/src/runtime/conversationEngine.d.ts +2 -0
  84. package/dist/src/runtime/conversationEngine.d.ts.map +1 -1
  85. package/dist/src/runtime/conversationEngine.js +10 -1
  86. package/dist/src/runtime/conversationEngine.js.map +1 -1
  87. package/dist/src/runtime/defaultHadamardAgents.d.ts.map +1 -1
  88. package/dist/src/runtime/defaultHadamardAgents.js +9 -47
  89. package/dist/src/runtime/defaultHadamardAgents.js.map +1 -1
  90. package/dist/src/runtime/effectiveAgentRunOptions.d.ts +49 -0
  91. package/dist/src/runtime/effectiveAgentRunOptions.d.ts.map +1 -0
  92. package/dist/src/runtime/effectiveAgentRunOptions.js +50 -0
  93. package/dist/src/runtime/effectiveAgentRunOptions.js.map +1 -0
  94. package/dist/src/runtime/externalAgentRunner.d.ts +25 -0
  95. package/dist/src/runtime/externalAgentRunner.d.ts.map +1 -0
  96. package/dist/src/runtime/externalAgentRunner.js +57 -0
  97. package/dist/src/runtime/externalAgentRunner.js.map +1 -0
  98. package/dist/src/runtime/hadamardAgentDefinitions.d.ts +15 -0
  99. package/dist/src/runtime/hadamardAgentDefinitions.d.ts.map +1 -1
  100. package/dist/src/runtime/hadamardAgentDefinitions.js +42 -2
  101. package/dist/src/runtime/hadamardAgentDefinitions.js.map +1 -1
  102. package/dist/src/runtime/hadamardAgents.d.ts +6 -0
  103. package/dist/src/runtime/hadamardAgents.d.ts.map +1 -1
  104. package/dist/src/runtime/hadamardAgents.js +52 -1
  105. package/dist/src/runtime/hadamardAgents.js.map +1 -1
  106. package/dist/src/runtime/hadamardPermissions.d.ts +1 -0
  107. package/dist/src/runtime/hadamardPermissions.d.ts.map +1 -1
  108. package/dist/src/runtime/hadamardPermissions.js +6 -0
  109. package/dist/src/runtime/hadamardPermissions.js.map +1 -1
  110. package/dist/src/runtime/tools.d.ts.map +1 -1
  111. package/dist/src/runtime/tools.js +2 -0
  112. package/dist/src/runtime/tools.js.map +1 -1
  113. package/dist/src/team/executorTarget.d.ts +26 -0
  114. package/dist/src/team/executorTarget.d.ts.map +1 -0
  115. package/dist/src/team/executorTarget.js +15 -0
  116. package/dist/src/team/executorTarget.js.map +1 -0
  117. package/dist/src/team/modelTeam.d.ts +5 -1
  118. package/dist/src/team/modelTeam.d.ts.map +1 -1
  119. package/dist/src/team/modelTeam.js +157 -41
  120. package/dist/src/team/modelTeam.js.map +1 -1
  121. package/dist/src/team/teamComposition.d.ts +20 -0
  122. package/dist/src/team/teamComposition.d.ts.map +1 -0
  123. package/dist/src/team/teamComposition.js +78 -0
  124. package/dist/src/team/teamComposition.js.map +1 -0
  125. package/dist/src/team/teamDefinitions.d.ts +10 -1
  126. package/dist/src/team/teamDefinitions.d.ts.map +1 -1
  127. package/dist/src/team/teamDefinitions.js +123 -16
  128. package/dist/src/team/teamDefinitions.js.map +1 -1
  129. package/dist/src/team/teamGraph.d.ts +1 -1
  130. package/dist/src/team/teamGraph.d.ts.map +1 -1
  131. package/dist/src/team/teamGraph.js +1 -1
  132. package/dist/src/team/teamGraph.js.map +1 -1
  133. package/dist/src/team/teamPrompts.d.ts.map +1 -1
  134. package/dist/src/team/teamPrompts.js +0 -4
  135. package/dist/src/team/teamPrompts.js.map +1 -1
  136. package/dist/src/team/teamProposalService.d.ts +9 -1
  137. package/dist/src/team/teamProposalService.d.ts.map +1 -1
  138. package/dist/src/team/teamProposalService.js +66 -6
  139. package/dist/src/team/teamProposalService.js.map +1 -1
  140. package/dist/src/team/teamPropose.d.ts +3 -1
  141. package/dist/src/team/teamPropose.d.ts.map +1 -1
  142. package/dist/src/team/teamPropose.js +16 -10
  143. package/dist/src/team/teamPropose.js.map +1 -1
  144. package/dist/src/team/teamRuntime.d.ts +5 -0
  145. package/dist/src/team/teamRuntime.d.ts.map +1 -1
  146. package/dist/src/team/teamRuntime.js +23 -5
  147. package/dist/src/team/teamRuntime.js.map +1 -1
  148. package/dist/src/team/workflowSquad.d.ts +10 -2
  149. package/dist/src/team/workflowSquad.d.ts.map +1 -1
  150. package/dist/src/team/workflowSquad.js +250 -12
  151. package/dist/src/team/workflowSquad.js.map +1 -1
  152. package/dist/src/tools/enterWorktree.d.ts.map +1 -1
  153. package/dist/src/tools/enterWorktree.js +3 -0
  154. package/dist/src/tools/enterWorktree.js.map +1 -1
  155. package/dist/src/tools/exaSearch.d.ts +2 -2
  156. package/dist/src/tools/exitWorktree.d.ts.map +1 -1
  157. package/dist/src/tools/exitWorktree.js +3 -1
  158. package/dist/src/tools/exitWorktree.js.map +1 -1
  159. package/dist/src/tools/hadamardCoreTools.d.ts +5 -14
  160. package/dist/src/tools/hadamardCoreTools.d.ts.map +1 -1
  161. package/dist/src/tools/hadamardCoreTools.js +31 -0
  162. package/dist/src/tools/hadamardCoreTools.js.map +1 -1
  163. package/dist/src/tools/hadamardFileTools.d.ts.map +1 -1
  164. package/dist/src/tools/hadamardFileTools.js +116 -38
  165. package/dist/src/tools/hadamardFileTools.js.map +1 -1
  166. package/dist/src/tools/planMode/PlanModeTools.js +2 -2
  167. package/dist/src/tools/planMode/PlanModeTools.js.map +1 -1
  168. package/dist/src/tui/hadamardTui.d.ts.map +1 -1
  169. package/dist/src/tui/hadamardTui.js +358 -69
  170. package/dist/src/tui/hadamardTui.js.map +1 -1
  171. package/dist/src/tui/pendingInput.d.ts +17 -0
  172. package/dist/src/tui/pendingInput.d.ts.map +1 -0
  173. package/dist/src/tui/pendingInput.js +23 -0
  174. package/dist/src/tui/pendingInput.js.map +1 -0
  175. package/dist/src/tui/reasoningDisplay.d.ts +13 -0
  176. package/dist/src/tui/reasoningDisplay.d.ts.map +1 -0
  177. package/dist/src/tui/reasoningDisplay.js +45 -0
  178. package/dist/src/tui/reasoningDisplay.js.map +1 -0
  179. package/dist/src/tui/screen.d.ts +11 -1
  180. package/dist/src/tui/screen.d.ts.map +1 -1
  181. package/dist/src/tui/screen.js +64 -34
  182. package/dist/src/tui/screen.js.map +1 -1
  183. package/dist/src/types.d.ts +171 -4
  184. package/dist/src/types.d.ts.map +1 -1
  185. package/dist/src/types.js.map +1 -1
  186. package/dist/src/ui/commandSurface.d.ts +8 -0
  187. package/dist/src/ui/commandSurface.d.ts.map +1 -1
  188. package/dist/src/ui/commandSurface.js +71 -7
  189. package/dist/src/ui/commandSurface.js.map +1 -1
  190. package/package.json +1 -1
  191. package/dist/src/gui/projectSettings.d.ts +0 -2
  192. package/dist/src/gui/projectSettings.d.ts.map +0 -1
  193. package/dist/src/gui/projectSettings.js +0 -2
  194. package/dist/src/gui/projectSettings.js.map +0 -1
@@ -41,6 +41,7 @@ import { policyPermissionMode, policyPermissionRules, } from '../policy/runtimeP
41
41
  import { TeammateStore } from '../storage/teammateStore.js';
42
42
  import { createCheckpointTools, FileChangeJournal, FileCheckpointService, } from '../checkpoint/index.js';
43
43
  import { SandboxExecutor } from '../sandbox/sandboxExecutor.js';
44
+ import { resolveSandboxPolicy } from '../sandbox/policyResolver.js';
44
45
  import { CodeIntelligenceService, createCodeIntelligenceTools, LanguageServerRegistry, } from '../codeIntel/index.js';
45
46
  import { HookRunner } from '../hooks/hookRunner.js';
46
47
  import { createPromptHookHandler } from '../hooks/handlers/promptHook.js';
@@ -52,6 +53,10 @@ import { createGitWorktreeWorkspace, } from '../workspace/hadamardWorkspace.js';
52
53
  import { HADAMARD_RUN_STATE_KEY, HadamardAgentsApi, createHadamardRunToolState, createHadamardTaskTool, summarizeHadamardAgentDefinition, } from './hadamardAgents.js';
53
54
  import { getDefaultHadamardAgents } from './defaultHadamardAgents.js';
54
55
  import { loadHadamardAgentDefinitions } from './hadamardAgentDefinitions.js';
56
+ import { migrateAgentProfilesToMarkdown } from '../config/agentDefinitionMigration.js';
57
+ import { resolveTargetRef } from '../manager/resolveTargetRef.js';
58
+ import { isExternalAgentRuntime, runExternalAgentOnce } from './externalAgentRunner.js';
59
+ import { resolveEffectiveAgentRunOptions } from './effectiveAgentRunOptions.js';
55
60
  import { HadamardSkillsApi, getDefaultHadamardBundledSkills, loadHadamardSkillDefinitions, resolveHadamardSkillPrompt, skillPathsMatch, summarizeHadamardSkillDefinition, } from './hadamardSkills.js';
56
61
  import { loadHadamardExternalSkillDefinitions } from './externalSkillRuntime.js';
57
62
  import { HadamardBackgroundTaskManager, HadamardBackgroundTasksApi, } from './hadamardBackgroundTasks.js';
@@ -454,6 +459,10 @@ export class HadamardAgentClient {
454
459
  sessionManager;
455
460
  sessionTurnCoordinator = new SessionTurnCoordinator();
456
461
  agentDefinitions;
462
+ /** §6-6: per-agent-session model clients resolved from definition.bridgeConfig. */
463
+ agentSessionModelClients = new Map();
464
+ /** External-CLI delegation runner (injectable for tests via CreateAgentSdkOptions). */
465
+ externalAgentRunner;
457
466
  skillDefinitions;
458
467
  /** Names of `paths:`-conditional skills activated by touching matching files. */
459
468
  activatedConditionalSkills = new Set();
@@ -474,7 +483,7 @@ export class HadamardAgentClient {
474
483
  * Idle restores never push; nested runs each own a slot.
475
484
  */
476
485
  conversationRestoreStack = [];
477
- constructor(config, store, executionStore, backgroundTaskStore, mailboxStore, teammateStore, modelApi, mcpManager, defaultTools, defaultMcpServers, hooks, agentDefinitions = [], skillDefinitions = [], defaultPermissionMode, defaultPermissions, defaultClassifier, defaultApprover, sessionManagerConfig, maxSubagentDepth = 1, maxSubagentFanout = 8, taskWorktreeCoordinator) {
486
+ constructor(config, store, executionStore, backgroundTaskStore, mailboxStore, teammateStore, modelApi, mcpManager, defaultTools, defaultMcpServers, hooks, agentDefinitions = [], skillDefinitions = [], defaultPermissionMode, defaultPermissions, defaultClassifier, defaultApprover, sessionManagerConfig, maxSubagentDepth = 1, maxSubagentFanout = 8, taskWorktreeCoordinator, externalAgentRunner) {
478
487
  this.config = config;
479
488
  this.store = store;
480
489
  this.backgroundTaskStore = backgroundTaskStore;
@@ -487,6 +496,7 @@ export class HadamardAgentClient {
487
496
  this.hooks = hooks;
488
497
  this.maxSubagentDepth = maxSubagentDepth;
489
498
  this.maxSubagentFanout = maxSubagentFanout;
499
+ this.externalAgentRunner = externalAgentRunner ?? runExternalAgentOnce;
490
500
  this.sessionManager = new SessionManager(this.store, sessionManagerConfig);
491
501
  this.sessionGraph = new SessionGraph(this.store);
492
502
  this.sessionForks = new SessionForkService(this.store);
@@ -798,6 +808,9 @@ export class HadamardAgentClient {
798
808
  ...(options.skills ?? []),
799
809
  ]
800
810
  : [...loadedSkills, ...(options.skills ?? [])];
811
+ // Unified agent store (S1a): auto-migrate legacy agent-configs.json into
812
+ // agents/*.md before loading definitions (idempotent, no-op once migrated).
813
+ migrateAgentProfilesToMarkdown(config.homeDir, path.join(config.homeDir, 'agents'));
801
814
  const loadedAgents = await loadHadamardAgentDefinitions({
802
815
  homeDir: config.homeDir,
803
816
  workDir: config.workDir,
@@ -841,7 +854,7 @@ export class HadamardAgentClient {
841
854
  client = new HadamardAgentClient(config, store, executionStore, backgroundTaskStore, mailboxStore, teammateStore, modelApi, mcpManager, defaultTools, defaultMcpServers, options.hooks, agentDefinitions, skillDefinitions, policyPermissionMode(config.effectivePolicy) ?? options.permissionMode, [
842
855
  ...policyPermissionRules(config.effectivePolicy),
843
856
  ...(options.permissions ?? []),
844
- ], options.classifier, options.approver, options.sessionManager, options.maxSubagentDepth, options.maxSubagentFanout, taskWorktreeCoordinator);
857
+ ], options.classifier, options.approver, options.sessionManager, options.maxSubagentDepth, options.maxSubagentFanout, taskWorktreeCoordinator, options.externalAgentRunner);
845
858
  const interruptedTasks = await client.backgroundTaskManager.reconcileInterruptedTasks();
846
859
  await client.reconcileInterruptedAgentExecutions(interruptedTasks);
847
860
  return client;
@@ -1165,24 +1178,101 @@ export class HadamardAgentClient {
1165
1178
  }
1166
1179
  }
1167
1180
  listAgentDefinitions() {
1168
- return [...this.agentDefinitions.values()].map(summarizeHadamardAgentDefinition);
1181
+ // subagent === false (§6-1): main-chat-only agents stay out of the
1182
+ // Agent/Task tool's available-subagents listing.
1183
+ return [...this.agentDefinitions.values()]
1184
+ .filter(definition => definition.subagent !== false)
1185
+ .map(summarizeHadamardAgentDefinition);
1169
1186
  }
1170
1187
  getAgentDefinition(agent) {
1171
1188
  const definition = this.agentDefinitions.get(agent);
1172
- return definition ? cloneAgentDefinition(definition) : undefined;
1189
+ // subagent === false: not resolvable as a delegation target, but still
1190
+ // activatable as a main-chat agent (requireAgentDefinition is unfiltered).
1191
+ if (!definition || definition.subagent === false)
1192
+ return undefined;
1193
+ return cloneAgentDefinition(definition);
1173
1194
  }
1174
1195
  async runWithAgent(agent, input, options = {}) {
1175
1196
  const definition = this.requireAgentDefinition(agent);
1197
+ if (isExternalAgentRuntime(definition.runtime)) {
1198
+ // External-CLI delegation (09 Aug 2026): one-shot bridge run on the
1199
+ // definition's runtime — no SDK session, no model-client resolution.
1200
+ const prompt = typeof input === 'string' ? input : extractTextFromContent(input);
1201
+ return this.runExternalDefinition(definition, prompt, {
1202
+ cwd: definition.cwd ?? this.config.workDir,
1203
+ signal: options.signal,
1204
+ });
1205
+ }
1206
+ // §6-6 model priority: caller-passed model/modelApi > definition's own
1207
+ // bridgeConfig client > inherited session client.
1208
+ const modelClient = options.model || options.modelApi
1209
+ ? undefined
1210
+ : await this.resolveDefinitionModelClient(definition);
1176
1211
  const mergedOptions = this.mergeAgentRunOptions(definition, options);
1212
+ if (modelClient) {
1213
+ mergedOptions.model = modelClient.model;
1214
+ mergedOptions.modelApi = modelClient.modelApi;
1215
+ }
1177
1216
  return this.run(input, mergedOptions);
1178
1217
  }
1218
+ /**
1219
+ * Run a definition on its external CLI runtime and fabricate the
1220
+ * AgentRunResult. The bridge result's native session id is intentionally
1221
+ * NOT exposed as a Hadamard sessionId — external runs are not resumable
1222
+ * through SendMessage.
1223
+ */
1224
+ async runExternalDefinition(definition, prompt, options) {
1225
+ const startedAt = nowIso();
1226
+ const run = await this.externalAgentRunner({
1227
+ runtime: definition.runtime.trim(),
1228
+ agentName: definition.name,
1229
+ prompt,
1230
+ systemPrompt: definition.systemPrompt,
1231
+ cwd: options.cwd,
1232
+ signal: options.signal,
1233
+ model: definition.model,
1234
+ permissionMode: definition.permissionMode,
1235
+ homeDir: this.config.homeDir,
1236
+ });
1237
+ const model = definition.model ?? definition.runtime ?? 'external';
1238
+ return {
1239
+ runId: createId(),
1240
+ model,
1241
+ text: run.text,
1242
+ message: {
1243
+ id: createId(),
1244
+ type: 'message',
1245
+ role: 'assistant',
1246
+ model,
1247
+ content: [{ type: 'text', text: run.text }],
1248
+ stop_reason: 'end_turn',
1249
+ stop_sequence: null,
1250
+ usage: { input_tokens: 0, output_tokens: 0 },
1251
+ },
1252
+ messages: [
1253
+ { role: 'user', content: prompt },
1254
+ { role: 'assistant', content: run.text },
1255
+ ],
1256
+ stopReason: 'end_turn',
1257
+ requests: [],
1258
+ toolCalls: [],
1259
+ startedAt,
1260
+ completedAt: nowIso(),
1261
+ };
1262
+ }
1179
1263
  async createAgentSession(agent, options = {}) {
1180
1264
  const definition = this.requireAgentDefinition(agent);
1181
- return this.createSession({
1265
+ const effective = resolveEffectiveAgentRunOptions(definition, {
1266
+ permissionModeOverride: options.permissionMode,
1267
+ });
1268
+ const session = await this.createSession({
1182
1269
  ...options,
1183
1270
  kind: options.kind ?? 'agent',
1184
1271
  model: options.model ?? definition.model,
1185
- systemPrompt: joinPromptParts(definition.systemPrompt, options.systemPrompt),
1272
+ // Keep the caller prompt as session state; the definition is composed at
1273
+ // send time so `extend` does not duplicate and `replace` stays exact.
1274
+ systemPrompt: options.systemPrompt,
1275
+ permissionMode: effective.permissionMode,
1186
1276
  metadata: {
1187
1277
  ...(definition.metadata ?? {}),
1188
1278
  ...(options.metadata ?? {}),
@@ -1195,6 +1285,15 @@ export class HadamardAgentClient {
1195
1285
  },
1196
1286
  },
1197
1287
  });
1288
+ // §6-6: a definition with bridgeConfig runs on its own provider config.
1289
+ // Resolve the client once per agent session; resolveSessionAgentOptions
1290
+ // (sync) applies it to every send on this session.
1291
+ if (definition.bridgeConfig && !options.model) {
1292
+ const modelClient = await this.resolveDefinitionModelClient(definition);
1293
+ if (modelClient)
1294
+ this.agentSessionModelClients.set(session.id, modelClient);
1295
+ }
1296
+ return session;
1198
1297
  }
1199
1298
  listSkillDefinitions() {
1200
1299
  return [...this.skillDefinitions.values()].map(summarizeHadamardSkillDefinition);
@@ -1267,6 +1366,7 @@ export class HadamardAgentClient {
1267
1366
  ...options,
1268
1367
  listAgentDefinitions: () => this.listAgentDefinitions(),
1269
1368
  getAgentDefinition: (agent) => this.getAgentDefinition(agent),
1369
+ listAvailableTools: () => this.defaultTools,
1270
1370
  runAgent: (agent, prompt, runOptions, delegation) => this.runDelegatedAgentTask(agent, prompt, runOptions, delegation),
1271
1371
  maxDepth: this.maxSubagentDepth,
1272
1372
  maxFanout: this.maxSubagentFanout,
@@ -1881,6 +1981,7 @@ export class HadamardAgentClient {
1881
1981
  }
1882
1982
  async executeRun(runId, input, options, session, streaming = false, emit, augmentations, skipRunStartedEvent = false, liveSession, deferPromptTooLongSettlement = false, skipInitialInput = false, onInitialInputCheckpointed) {
1883
1983
  const workDir = this.resolveRunWorkDir(options);
1984
+ let activeWorkDir = workDir;
1884
1985
  const model = this.resolveModel(options.model ?? session?.model);
1885
1986
  const goalService = await this.resolveGoalService(session, liveSession);
1886
1987
  let goalExecutionDecision = { kind: 'run', mode: 'work' };
@@ -1955,7 +2056,13 @@ export class HadamardAgentClient {
1955
2056
  ...serializeAgentExecutionIdentity(executionIdentity),
1956
2057
  [HADAMARD_RUN_STATE_KEY]: createHadamardRunToolState(),
1957
2058
  };
1958
- const mergedTools = filterAgentTools(mergeUniqueByName(options.__hadamardUseDefaultTools === false ? [] : this.defaultTools, options.tools ?? []), options.__hadamardAllowedTools, options.__hadamardDisallowedTools);
2059
+ const workspaceAccess = options.__hadamardWorkspaceAccess ?? options.workspaceAccess;
2060
+ const sandboxExecutor = this.sandboxExecutorForWorkDir(workDir, workspaceAccess);
2061
+ const workspaceProcessDenylist = workspaceAccess === 'workspace'
2062
+ && !sandboxExecutor.capability.filesystemIsolation
2063
+ ? ['Bash', 'PowerShell', 'EnterWorktree', 'ExitWorktree']
2064
+ : [];
2065
+ const mergedTools = filterAgentTools(mergeUniqueByName(options.__hadamardUseDefaultTools === false ? [] : this.defaultTools, options.tools ?? []), options.__hadamardAllowedTools ?? options.allowedTools, [...(options.__hadamardDisallowedTools ?? []), ...workspaceProcessDenylist]);
1959
2066
  // Goal runtime contract: when a session exists, expose the active goal to
1960
2067
  // the model (short context in the system prompt + GetGoal/CreateGoal/
1961
2068
  // UpdateGoal tools). The GoalService is the single authority over goal
@@ -1971,7 +2078,7 @@ export class HadamardAgentClient {
1971
2078
  const goal = await goalService.read();
1972
2079
  goalPromptPart = buildGoalPrompt(goal, { decision: goalExecutionDecision });
1973
2080
  const toolsWithGoal = mergeUniqueByName(goalTools, createGoalTools({ getGoalService: () => goalService }));
1974
- goalTools = filterAgentTools(toolsWithGoal, options.__hadamardAllowedTools, options.__hadamardDisallowedTools);
2081
+ goalTools = filterAgentTools(toolsWithGoal, options.__hadamardAllowedTools ?? options.allowedTools, [...(options.__hadamardDisallowedTools ?? []), ...workspaceProcessDenylist]);
1975
2082
  }
1976
2083
  // Collect tool prompts for system prompt assembly
1977
2084
  const toolPromptParts = await collectToolPrompts(goalTools, {
@@ -1983,15 +2090,15 @@ export class HadamardAgentClient {
1983
2090
  ...(goalPromptPart ? [goalPromptPart] : []),
1984
2091
  ...toolPromptParts,
1985
2092
  ]);
1986
- const sandboxExecutor = this.sandboxExecutorForWorkDir(workDir);
1987
- const runtimeConfig = options.__hadamardMaxToolIterations || workDir !== this.config.workDir
2093
+ const runMaxToolIterations = options.__hadamardMaxToolIterations ?? options.maxToolIterations;
2094
+ const runtimeConfig = runMaxToolIterations || workDir !== this.config.workDir
1988
2095
  ? {
1989
2096
  ...this.config,
1990
2097
  workDir,
1991
2098
  sandbox: sandboxExecutor.policy,
1992
2099
  sandboxCapabilities: sandboxExecutor.capability,
1993
- ...(options.__hadamardMaxToolIterations
1994
- ? { maxToolIterations: options.__hadamardMaxToolIterations }
2100
+ ...(runMaxToolIterations
2101
+ ? { maxToolIterations: runMaxToolIterations }
1995
2102
  : {}),
1996
2103
  }
1997
2104
  : this.config;
@@ -2103,7 +2210,7 @@ export class HadamardAgentClient {
2103
2210
  updatedAt: nowIso(),
2104
2211
  metadata: {
2105
2212
  ...current.metadata,
2106
- __hadamardWorkDir: workDir,
2213
+ __hadamardWorkDir: activeWorkDir,
2107
2214
  ...(options.metadata ?? {}),
2108
2215
  ...serializeAgentExecutionIdentity(executionIdentity),
2109
2216
  },
@@ -2134,6 +2241,15 @@ export class HadamardAgentClient {
2134
2241
  modelApi: options.modelApi ?? this.modelApi,
2135
2242
  config: runtimeConfig,
2136
2243
  mcpManager: this.mcpManager,
2244
+ sessionWorkDir: activeWorkDir,
2245
+ onSessionWorkDirChange: (nextWorkDir) => {
2246
+ activeWorkDir = nextWorkDir;
2247
+ options.__hadamardWorkDir = nextWorkDir;
2248
+ options.metadata = {
2249
+ ...(options.metadata ?? {}),
2250
+ __hadamardWorkDir: nextWorkDir,
2251
+ };
2252
+ },
2137
2253
  fileChangeJournal: fileCheckpointStarted ? this.fileChangeJournal : undefined,
2138
2254
  sandboxExecutor,
2139
2255
  typedHookRunner: this.typedHookRunner,
@@ -2782,6 +2898,23 @@ export class HadamardAgentClient {
2782
2898
  });
2783
2899
  let edgeStarted = false;
2784
2900
  try {
2901
+ if (isExternalAgentRuntime(definition.runtime)) {
2902
+ // External-CLI delegation: one-shot bridge run in the prepared (maybe
2903
+ // worktree-isolated) workspace; no Hadamard session is created.
2904
+ edgeStarted = await this.tryStartExecutionEdge(execution.edge);
2905
+ const result = await this.runExternalDefinition(definition, prompt, {
2906
+ cwd: prepared.workDir,
2907
+ signal: runOptions.signal,
2908
+ });
2909
+ const retained = await this.finalizeDelegatedWorkspace(prepared.workspace);
2910
+ await this.tryCompleteExecutionEdge(execution.edge, result.text);
2911
+ return {
2912
+ result,
2913
+ sessionId: '',
2914
+ worktreePath: retained ? prepared.workspace?.path : undefined,
2915
+ worktreeBranch: retained ? prepared.workspace?.metadata.branch : undefined,
2916
+ };
2917
+ }
2785
2918
  const session = await this.createAgentSession(agent, {
2786
2919
  id: childSessionId,
2787
2920
  kind: 'agent',
@@ -3041,6 +3174,13 @@ export class HadamardAgentClient {
3041
3174
  }
3042
3175
  async launchBackgroundAgentTask(agent, prompt, options, runOptions = {}, delegation = { description: prompt }) {
3043
3176
  const definition = this.requireAgentDefinition(agent);
3177
+ if (isExternalAgentRuntime(definition.runtime)) {
3178
+ // External runtimes are one-shot CLI runs — there is no Hadamard session
3179
+ // to drive in the background, so fail loudly instead of silently
3180
+ // falling back to the SDK.
3181
+ throw new Error(`Agent "${definition.name}" uses external runtime "${definition.runtime}"; `
3182
+ + 'background delegation is not supported for external runtimes yet — run it in the foreground.');
3183
+ }
3044
3184
  const prepared = await this.prepareDelegatedWorkspace(definition, delegation);
3045
3185
  const childSessionId = createId();
3046
3186
  const execution = this.delegatedExecutionContext(definition, delegation, runOptions, prepared.workDir, childSessionId, options);
@@ -3716,8 +3856,16 @@ export class HadamardAgentClient {
3716
3856
  internal.__hadamardPersistedWorkDir ??
3717
3857
  this.config.workDir);
3718
3858
  }
3719
- sandboxExecutorForWorkDir(workDir) {
3859
+ sandboxExecutorForWorkDir(workDir, workspaceAccess) {
3720
3860
  const resolved = path.resolve(workDir);
3861
+ if (workspaceAccess === 'workspace') {
3862
+ return new SandboxExecutor(resolveSandboxPolicy(resolved, this.config.sandbox, {
3863
+ readRoots: [resolved],
3864
+ writableRoots: [resolved],
3865
+ allowUserDisable: false,
3866
+ source: 'agent:workspace',
3867
+ }));
3868
+ }
3721
3869
  if (resolved === path.resolve(this.config.workDir))
3722
3870
  return this.sandboxExecutor;
3723
3871
  const remap = (roots) => roots.map(root => {
@@ -3755,6 +3903,7 @@ export class HadamardAgentClient {
3755
3903
  : undefined;
3756
3904
  const sessionOptions = {
3757
3905
  ...options,
3906
+ systemPrompt: options.systemPrompt ?? session.systemPrompt,
3758
3907
  __hadamardPersistedWorkDir: persistedWorkDir,
3759
3908
  };
3760
3909
  const agentName = typeof session.metadata.__hadamardAgentDefinition === 'string'
@@ -3763,7 +3912,33 @@ export class HadamardAgentClient {
3763
3912
  if (!agentName) {
3764
3913
  return sessionOptions;
3765
3914
  }
3766
- return this.mergeAgentRunOptions(this.requireAgentDefinition(agentName), sessionOptions);
3915
+ const merged = this.mergeAgentRunOptions(this.requireAgentDefinition(agentName), sessionOptions);
3916
+ // §6-6: apply the session's definition-resolved model client (see
3917
+ // createAgentSession); a caller-passed model/modelApi still wins.
3918
+ const modelClient = this.agentSessionModelClients.get(session.id);
3919
+ if (modelClient && !sessionOptions.modelApi) {
3920
+ merged.model = sessionOptions.model ?? modelClient.model;
3921
+ merged.modelApi = modelClient.modelApi;
3922
+ }
3923
+ return merged;
3924
+ }
3925
+ /**
3926
+ * §6-6: resolve a definition's own model client from its bridgeConfig via
3927
+ * the central target resolver. A missing config throws BrokenReferenceError
3928
+ * — in plain SDK context that surfaces as a hard delegation error (the GUI
3929
+ * fallback-toggle semantics live in the GUI layer, not here).
3930
+ */
3931
+ async resolveDefinitionModelClient(definition) {
3932
+ if (!definition.bridgeConfig?.trim())
3933
+ return undefined;
3934
+ const resolved = resolveTargetRef({ kind: 'model', config: definition.bridgeConfig.trim(), model: definition.model ?? '' }, { homeDir: this.config.homeDir });
3935
+ const routed = await buildRouteModelApi({
3936
+ model: resolved.model || 'default',
3937
+ provider: resolved.provider,
3938
+ baseURL: resolved.baseURL,
3939
+ apiKey: resolved.apiKey,
3940
+ });
3941
+ return { model: routed.model, modelApi: routed.modelApi };
3767
3942
  }
3768
3943
  mergeAgentRunOptions(definition, options) {
3769
3944
  const availableMcpServers = new Set([
@@ -3776,12 +3951,24 @@ export class HadamardAgentClient {
3776
3951
  throw new Error(`Agent "${definition.name}" requires unavailable MCP servers: ${missingMcpServers.join(', ')}.`);
3777
3952
  }
3778
3953
  const nestedAgentDenylist = definition.allowNestedAgents === true ? [] : ['Agent', 'Task'];
3954
+ const effective = resolveEffectiveAgentRunOptions(definition, {
3955
+ systemPrompt: options.systemPrompt,
3956
+ permissionModeOverride: options.permissionMode,
3957
+ effortOverride: options.effort,
3958
+ });
3959
+ const signal = typeof definition.timeoutMs === 'number' && definition.timeoutMs > 0
3960
+ ? combineAbortSignals(options.signal, AbortSignal.timeout(definition.timeoutMs))
3961
+ : options.signal;
3779
3962
  return {
3780
3963
  ...options,
3781
- systemPrompt: joinPromptParts(definition.systemPrompt, options.systemPrompt),
3964
+ systemPrompt: effective.systemPrompt,
3782
3965
  model: options.model ?? definition.model,
3783
- effort: options.effort ?? definition.effort,
3784
- permissionMode: options.permissionMode ?? definition.permissionMode,
3966
+ effort: effective.effort,
3967
+ permissionMode: effective.permissionMode,
3968
+ maxTokens: options.maxTokens ?? effective.maxTokens,
3969
+ temperature: options.temperature ?? effective.temperature,
3970
+ topP: options.topP ?? effective.topP,
3971
+ signal,
3785
3972
  metadata: {
3786
3973
  ...(definition.metadata ?? {}),
3787
3974
  ...(options.metadata ?? {}),
@@ -3792,10 +3979,11 @@ export class HadamardAgentClient {
3792
3979
  mcpServers: [...(definition.mcpServers ?? []), ...(options.mcpServers ?? [])],
3793
3980
  __hadamardUseDefaultTools: definition.inheritDefaultTools !== false,
3794
3981
  __hadamardUseDefaultMcpServers: definition.inheritDefaultMcpServers !== false,
3795
- __hadamardMaxToolIterations: definition.maxToolIterations ?? definition.maxTurns,
3796
- __hadamardAllowedTools: definition.allowedTools
3797
- ? [...definition.allowedTools]
3982
+ __hadamardMaxToolIterations: effective.maxToolIterations ?? definition.maxTurns,
3983
+ __hadamardAllowedTools: options.allowedTools ?? effective.allowedTools
3984
+ ? [...(options.allowedTools ?? effective.allowedTools)]
3798
3985
  : undefined,
3986
+ __hadamardWorkspaceAccess: options.workspaceAccess ?? effective.workspaceAccess,
3799
3987
  __hadamardDisallowedTools: [
3800
3988
  ...(definition.disallowedTools ?? []),
3801
3989
  ...nestedAgentDenylist,