pilotswarm-sdk 0.5.63 → 0.5.65

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 (289) hide show
  1. package/api/src/admin-diagnostics.d.ts +12 -0
  2. package/api/src/admin-diagnostics.js +38 -1
  3. package/api/src/http-api-transport.js +26 -0
  4. package/api/src/protocol.js +15 -0
  5. package/dist/activity-routing.d.ts +21 -0
  6. package/dist/activity-routing.d.ts.map +1 -0
  7. package/dist/activity-routing.js +32 -0
  8. package/dist/activity-routing.js.map +1 -0
  9. package/dist/agent-discovery.d.ts +35 -0
  10. package/dist/agent-discovery.d.ts.map +1 -0
  11. package/dist/agent-discovery.js +107 -0
  12. package/dist/agent-discovery.js.map +1 -0
  13. package/dist/client.d.ts +9 -1
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/client.js +94 -12
  16. package/dist/client.js.map +1 -1
  17. package/dist/cms-migrations.d.ts.map +1 -1
  18. package/dist/cms-migrations.js +4 -0
  19. package/dist/cms-migrations.js.map +1 -1
  20. package/dist/cms.d.ts +3 -0
  21. package/dist/cms.d.ts.map +1 -1
  22. package/dist/cms.js +7 -0
  23. package/dist/cms.js.map +1 -1
  24. package/dist/feature-flag-cache.d.ts +40 -0
  25. package/dist/feature-flag-cache.d.ts.map +1 -0
  26. package/dist/feature-flag-cache.js +125 -0
  27. package/dist/feature-flag-cache.js.map +1 -0
  28. package/dist/feature-flags.d.ts +68 -0
  29. package/dist/feature-flags.d.ts.map +1 -0
  30. package/dist/feature-flags.js +45 -0
  31. package/dist/feature-flags.js.map +1 -0
  32. package/dist/feature-store.d.ts +55 -0
  33. package/dist/feature-store.d.ts.map +1 -0
  34. package/dist/feature-store.js +106 -0
  35. package/dist/feature-store.js.map +1 -0
  36. package/dist/feature-tools.d.ts +94 -0
  37. package/dist/feature-tools.d.ts.map +1 -0
  38. package/dist/feature-tools.js +60 -0
  39. package/dist/feature-tools.js.map +1 -0
  40. package/dist/index.d.ts +6 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +4 -0
  43. package/dist/index.js.map +1 -1
  44. package/dist/managed-session.d.ts +4 -0
  45. package/dist/managed-session.d.ts.map +1 -1
  46. package/dist/managed-session.js +120 -23
  47. package/dist/managed-session.js.map +1 -1
  48. package/dist/management-client.d.ts +18 -0
  49. package/dist/management-client.d.ts.map +1 -1
  50. package/dist/management-client.js +19 -0
  51. package/dist/management-client.js.map +1 -1
  52. package/dist/migrations/feature-flags-0077.d.ts +3 -0
  53. package/dist/migrations/feature-flags-0077.d.ts.map +1 -0
  54. package/dist/migrations/feature-flags-0077.js +271 -0
  55. package/dist/migrations/feature-flags-0077.js.map +1 -0
  56. package/dist/migrations/native-tasks-default-policy-0078.d.ts +3 -0
  57. package/dist/migrations/native-tasks-default-policy-0078.d.ts.map +1 -0
  58. package/dist/migrations/native-tasks-default-policy-0078.js +21 -0
  59. package/dist/migrations/native-tasks-default-policy-0078.js.map +1 -0
  60. package/dist/native-subagents.d.ts +25 -0
  61. package/dist/native-subagents.d.ts.map +1 -0
  62. package/dist/native-subagents.js +191 -0
  63. package/dist/native-subagents.js.map +1 -0
  64. package/dist/native-task-observer.d.ts +87 -0
  65. package/dist/native-task-observer.d.ts.map +1 -0
  66. package/dist/native-task-observer.js +268 -0
  67. package/dist/native-task-observer.js.map +1 -0
  68. package/dist/orchestration/agents.d.ts +8 -3
  69. package/dist/orchestration/agents.d.ts.map +1 -1
  70. package/dist/orchestration/agents.js +87 -36
  71. package/dist/orchestration/agents.js.map +1 -1
  72. package/dist/orchestration/index.d.ts +2 -2
  73. package/dist/orchestration/index.js +1 -1
  74. package/dist/orchestration/lifecycle.js +1 -1
  75. package/dist/orchestration/lifecycle.js.map +1 -1
  76. package/dist/orchestration/runtime.d.ts +1 -1
  77. package/dist/orchestration/runtime.d.ts.map +1 -1
  78. package/dist/orchestration/runtime.js +18 -4
  79. package/dist/orchestration/runtime.js.map +1 -1
  80. package/dist/orchestration/turn.d.ts.map +1 -1
  81. package/dist/orchestration/turn.js +3 -5
  82. package/dist/orchestration/turn.js.map +1 -1
  83. package/dist/orchestration-registry.d.ts.map +1 -1
  84. package/dist/orchestration-registry.js +12 -2
  85. package/dist/orchestration-registry.js.map +1 -1
  86. package/dist/orchestration-version.d.ts +1 -1
  87. package/dist/orchestration-version.js +1 -1
  88. package/dist/orchestration.d.ts +2 -2
  89. package/dist/orchestration.js +1 -1
  90. package/dist/orchestration_1_0_46.d.ts +1 -1
  91. package/dist/orchestration_1_0_47.d.ts +1 -1
  92. package/dist/orchestration_1_0_48.d.ts +1 -1
  93. package/dist/orchestration_1_0_49.d.ts +1 -1
  94. package/dist/orchestration_1_0_50.d.ts +1 -1
  95. package/dist/orchestration_1_0_73/agents.d.ts +61 -0
  96. package/dist/orchestration_1_0_73/agents.d.ts.map +1 -0
  97. package/dist/orchestration_1_0_73/agents.js +843 -0
  98. package/dist/orchestration_1_0_73/agents.js.map +1 -0
  99. package/dist/orchestration_1_0_73/index.d.ts +24 -0
  100. package/dist/orchestration_1_0_73/index.d.ts.map +1 -0
  101. package/dist/orchestration_1_0_73/index.js +13 -0
  102. package/dist/orchestration_1_0_73/index.js.map +1 -0
  103. package/dist/orchestration_1_0_73/lifecycle.d.ts +51 -0
  104. package/dist/orchestration_1_0_73/lifecycle.d.ts.map +1 -0
  105. package/dist/orchestration_1_0_73/lifecycle.js +981 -0
  106. package/dist/orchestration_1_0_73/lifecycle.js.map +1 -0
  107. package/dist/orchestration_1_0_73/queue.d.ts +20 -0
  108. package/dist/orchestration_1_0_73/queue.d.ts.map +1 -0
  109. package/dist/orchestration_1_0_73/queue.js +894 -0
  110. package/dist/orchestration_1_0_73/queue.js.map +1 -0
  111. package/dist/orchestration_1_0_73/runtime.d.ts +31 -0
  112. package/dist/orchestration_1_0_73/runtime.d.ts.map +1 -0
  113. package/dist/orchestration_1_0_73/runtime.js +230 -0
  114. package/dist/orchestration_1_0_73/runtime.js.map +1 -0
  115. package/dist/orchestration_1_0_73/state.d.ts +214 -0
  116. package/dist/orchestration_1_0_73/state.d.ts.map +1 -0
  117. package/dist/orchestration_1_0_73/state.js +178 -0
  118. package/dist/orchestration_1_0_73/state.js.map +1 -0
  119. package/dist/orchestration_1_0_73/turn.d.ts +34 -0
  120. package/dist/orchestration_1_0_73/turn.d.ts.map +1 -0
  121. package/dist/orchestration_1_0_73/turn.js +1435 -0
  122. package/dist/orchestration_1_0_73/turn.js.map +1 -0
  123. package/dist/orchestration_1_0_73/utils.d.ts +39 -0
  124. package/dist/orchestration_1_0_73/utils.d.ts.map +1 -0
  125. package/dist/orchestration_1_0_73/utils.js +322 -0
  126. package/dist/orchestration_1_0_73/utils.js.map +1 -0
  127. package/dist/orchestration_1_0_74/agents.d.ts +61 -0
  128. package/dist/orchestration_1_0_74/agents.d.ts.map +1 -0
  129. package/dist/orchestration_1_0_74/agents.js +889 -0
  130. package/dist/orchestration_1_0_74/agents.js.map +1 -0
  131. package/dist/orchestration_1_0_74/index.d.ts +24 -0
  132. package/dist/orchestration_1_0_74/index.d.ts.map +1 -0
  133. package/dist/orchestration_1_0_74/index.js +13 -0
  134. package/dist/orchestration_1_0_74/index.js.map +1 -0
  135. package/dist/orchestration_1_0_74/lifecycle.d.ts +51 -0
  136. package/dist/orchestration_1_0_74/lifecycle.d.ts.map +1 -0
  137. package/dist/orchestration_1_0_74/lifecycle.js +981 -0
  138. package/dist/orchestration_1_0_74/lifecycle.js.map +1 -0
  139. package/dist/orchestration_1_0_74/queue.d.ts +20 -0
  140. package/dist/orchestration_1_0_74/queue.d.ts.map +1 -0
  141. package/dist/orchestration_1_0_74/queue.js +894 -0
  142. package/dist/orchestration_1_0_74/queue.js.map +1 -0
  143. package/dist/orchestration_1_0_74/runtime.d.ts +31 -0
  144. package/dist/orchestration_1_0_74/runtime.d.ts.map +1 -0
  145. package/dist/orchestration_1_0_74/runtime.js +232 -0
  146. package/dist/orchestration_1_0_74/runtime.js.map +1 -0
  147. package/dist/orchestration_1_0_74/state.d.ts +214 -0
  148. package/dist/orchestration_1_0_74/state.d.ts.map +1 -0
  149. package/dist/orchestration_1_0_74/state.js +178 -0
  150. package/dist/orchestration_1_0_74/state.js.map +1 -0
  151. package/dist/orchestration_1_0_74/turn.d.ts +34 -0
  152. package/dist/orchestration_1_0_74/turn.d.ts.map +1 -0
  153. package/dist/orchestration_1_0_74/turn.js +1435 -0
  154. package/dist/orchestration_1_0_74/turn.js.map +1 -0
  155. package/dist/orchestration_1_0_74/utils.d.ts +39 -0
  156. package/dist/orchestration_1_0_74/utils.d.ts.map +1 -0
  157. package/dist/orchestration_1_0_74/utils.js +322 -0
  158. package/dist/orchestration_1_0_74/utils.js.map +1 -0
  159. package/dist/orchestration_1_0_75/agents.d.ts +61 -0
  160. package/dist/orchestration_1_0_75/agents.d.ts.map +1 -0
  161. package/dist/orchestration_1_0_75/agents.js +887 -0
  162. package/dist/orchestration_1_0_75/agents.js.map +1 -0
  163. package/dist/orchestration_1_0_75/index.d.ts +24 -0
  164. package/dist/orchestration_1_0_75/index.d.ts.map +1 -0
  165. package/dist/orchestration_1_0_75/index.js +13 -0
  166. package/dist/orchestration_1_0_75/index.js.map +1 -0
  167. package/dist/orchestration_1_0_75/lifecycle.d.ts +51 -0
  168. package/dist/orchestration_1_0_75/lifecycle.d.ts.map +1 -0
  169. package/dist/orchestration_1_0_75/lifecycle.js +981 -0
  170. package/dist/orchestration_1_0_75/lifecycle.js.map +1 -0
  171. package/dist/orchestration_1_0_75/queue.d.ts +20 -0
  172. package/dist/orchestration_1_0_75/queue.d.ts.map +1 -0
  173. package/dist/orchestration_1_0_75/queue.js +894 -0
  174. package/dist/orchestration_1_0_75/queue.js.map +1 -0
  175. package/dist/orchestration_1_0_75/runtime.d.ts +31 -0
  176. package/dist/orchestration_1_0_75/runtime.d.ts.map +1 -0
  177. package/dist/orchestration_1_0_75/runtime.js +239 -0
  178. package/dist/orchestration_1_0_75/runtime.js.map +1 -0
  179. package/dist/orchestration_1_0_75/state.d.ts +214 -0
  180. package/dist/orchestration_1_0_75/state.d.ts.map +1 -0
  181. package/dist/orchestration_1_0_75/state.js +178 -0
  182. package/dist/orchestration_1_0_75/state.js.map +1 -0
  183. package/dist/orchestration_1_0_75/turn.d.ts +34 -0
  184. package/dist/orchestration_1_0_75/turn.d.ts.map +1 -0
  185. package/dist/orchestration_1_0_75/turn.js +1435 -0
  186. package/dist/orchestration_1_0_75/turn.js.map +1 -0
  187. package/dist/orchestration_1_0_75/utils.d.ts +39 -0
  188. package/dist/orchestration_1_0_75/utils.d.ts.map +1 -0
  189. package/dist/orchestration_1_0_75/utils.js +322 -0
  190. package/dist/orchestration_1_0_75/utils.js.map +1 -0
  191. package/dist/orchestration_1_0_76/agents.d.ts +61 -0
  192. package/dist/orchestration_1_0_76/agents.d.ts.map +1 -0
  193. package/dist/orchestration_1_0_76/agents.js +865 -0
  194. package/dist/orchestration_1_0_76/agents.js.map +1 -0
  195. package/dist/orchestration_1_0_76/index.d.ts +24 -0
  196. package/dist/orchestration_1_0_76/index.d.ts.map +1 -0
  197. package/dist/orchestration_1_0_76/index.js +13 -0
  198. package/dist/orchestration_1_0_76/index.js.map +1 -0
  199. package/dist/orchestration_1_0_76/lifecycle.d.ts +51 -0
  200. package/dist/orchestration_1_0_76/lifecycle.d.ts.map +1 -0
  201. package/dist/orchestration_1_0_76/lifecycle.js +981 -0
  202. package/dist/orchestration_1_0_76/lifecycle.js.map +1 -0
  203. package/dist/orchestration_1_0_76/queue.d.ts +20 -0
  204. package/dist/orchestration_1_0_76/queue.d.ts.map +1 -0
  205. package/dist/orchestration_1_0_76/queue.js +894 -0
  206. package/dist/orchestration_1_0_76/queue.js.map +1 -0
  207. package/dist/orchestration_1_0_76/runtime.d.ts +31 -0
  208. package/dist/orchestration_1_0_76/runtime.d.ts.map +1 -0
  209. package/dist/orchestration_1_0_76/runtime.js +239 -0
  210. package/dist/orchestration_1_0_76/runtime.js.map +1 -0
  211. package/dist/orchestration_1_0_76/state.d.ts +214 -0
  212. package/dist/orchestration_1_0_76/state.d.ts.map +1 -0
  213. package/dist/orchestration_1_0_76/state.js +178 -0
  214. package/dist/orchestration_1_0_76/state.js.map +1 -0
  215. package/dist/orchestration_1_0_76/turn.d.ts +34 -0
  216. package/dist/orchestration_1_0_76/turn.d.ts.map +1 -0
  217. package/dist/orchestration_1_0_76/turn.js +1435 -0
  218. package/dist/orchestration_1_0_76/turn.js.map +1 -0
  219. package/dist/orchestration_1_0_76/utils.d.ts +39 -0
  220. package/dist/orchestration_1_0_76/utils.d.ts.map +1 -0
  221. package/dist/orchestration_1_0_76/utils.js +322 -0
  222. package/dist/orchestration_1_0_76/utils.js.map +1 -0
  223. package/dist/orchestration_1_0_77/agents.d.ts +66 -0
  224. package/dist/orchestration_1_0_77/agents.d.ts.map +1 -0
  225. package/dist/orchestration_1_0_77/agents.js +895 -0
  226. package/dist/orchestration_1_0_77/agents.js.map +1 -0
  227. package/dist/orchestration_1_0_77/index.d.ts +24 -0
  228. package/dist/orchestration_1_0_77/index.d.ts.map +1 -0
  229. package/dist/orchestration_1_0_77/index.js +13 -0
  230. package/dist/orchestration_1_0_77/index.js.map +1 -0
  231. package/dist/orchestration_1_0_77/lifecycle.d.ts +51 -0
  232. package/dist/orchestration_1_0_77/lifecycle.d.ts.map +1 -0
  233. package/dist/orchestration_1_0_77/lifecycle.js +981 -0
  234. package/dist/orchestration_1_0_77/lifecycle.js.map +1 -0
  235. package/dist/orchestration_1_0_77/queue.d.ts +20 -0
  236. package/dist/orchestration_1_0_77/queue.d.ts.map +1 -0
  237. package/dist/orchestration_1_0_77/queue.js +894 -0
  238. package/dist/orchestration_1_0_77/queue.js.map +1 -0
  239. package/dist/orchestration_1_0_77/runtime.d.ts +31 -0
  240. package/dist/orchestration_1_0_77/runtime.d.ts.map +1 -0
  241. package/dist/orchestration_1_0_77/runtime.js +239 -0
  242. package/dist/orchestration_1_0_77/runtime.js.map +1 -0
  243. package/dist/orchestration_1_0_77/state.d.ts +214 -0
  244. package/dist/orchestration_1_0_77/state.d.ts.map +1 -0
  245. package/dist/orchestration_1_0_77/state.js +178 -0
  246. package/dist/orchestration_1_0_77/state.js.map +1 -0
  247. package/dist/orchestration_1_0_77/turn.d.ts +34 -0
  248. package/dist/orchestration_1_0_77/turn.d.ts.map +1 -0
  249. package/dist/orchestration_1_0_77/turn.js +1433 -0
  250. package/dist/orchestration_1_0_77/turn.js.map +1 -0
  251. package/dist/orchestration_1_0_77/utils.d.ts +39 -0
  252. package/dist/orchestration_1_0_77/utils.d.ts.map +1 -0
  253. package/dist/orchestration_1_0_77/utils.js +322 -0
  254. package/dist/orchestration_1_0_77/utils.js.map +1 -0
  255. package/dist/reserved-tool-names.d.ts +5 -0
  256. package/dist/reserved-tool-names.d.ts.map +1 -0
  257. package/dist/reserved-tool-names.js +102 -0
  258. package/dist/reserved-tool-names.js.map +1 -0
  259. package/dist/session-manager.d.ts +31 -1
  260. package/dist/session-manager.d.ts.map +1 -1
  261. package/dist/session-manager.js +343 -102
  262. package/dist/session-manager.js.map +1 -1
  263. package/dist/session-proxy.d.ts +28 -3
  264. package/dist/session-proxy.d.ts.map +1 -1
  265. package/dist/session-proxy.js +192 -71
  266. package/dist/session-proxy.js.map +1 -1
  267. package/dist/session-store.d.ts +2 -0
  268. package/dist/session-store.d.ts.map +1 -1
  269. package/dist/session-store.js +18 -2
  270. package/dist/session-store.js.map +1 -1
  271. package/dist/types.d.ts +25 -3
  272. package/dist/types.d.ts.map +1 -1
  273. package/dist/types.js.map +1 -1
  274. package/dist/web/generated-op-methods.d.ts +96 -0
  275. package/dist/web/generated-op-methods.d.ts.map +1 -1
  276. package/dist/web/generated-op-methods.js +24 -0
  277. package/dist/web/generated-op-methods.js.map +1 -1
  278. package/dist/web/web-management-client.d.ts +13 -0
  279. package/dist/web/web-management-client.d.ts.map +1 -1
  280. package/dist/web/web-management-client.js +12 -0
  281. package/dist/web/web-management-client.js.map +1 -1
  282. package/dist/worker.d.ts +13 -3
  283. package/dist/worker.d.ts.map +1 -1
  284. package/dist/worker.js +150 -110
  285. package/dist/worker.js.map +1 -1
  286. package/package.json +4 -3
  287. package/plugins/mgmt/agents/pilotswarm.agent.md +18 -1
  288. package/plugins/mgmt/agents/resourcemgr.agent.md +18 -1
  289. package/plugins/system/agents/default.agent.md +16 -7
@@ -1,6 +1,7 @@
1
+ import { HANDOFF_ACTIVITY_NAMES, routeHandoffActivity, routedActivityName, registerHandoffActivity } from "./activity-routing.js";
1
2
  import nodeCrypto from "node:crypto";
2
3
  import { createCopilotClient } from "./copilot-client.js";
3
- import { isSessionLockAcquireTimeoutError } from "./session-manager.js";
4
+ import { BoundAgentPackageUnavailableError, isSessionLockAcquireTimeoutError, PackageToolBindingError, } from "./session-manager.js";
4
5
  import { extractCanvasAppManifest, canvasAppCard, normalizeCanvasResponseContract } from "./canvas-app-manifest.js";
5
6
  import { readCanvasKv, writeCanvasKv } from "./canvas-kv.js";
6
7
  import { publishCanvasApp, findCanvasApp } from "./canvas-app-catalog.js";
@@ -37,6 +38,13 @@ import { attemptStoreRecovery, runTurnCommit, runTurnPreamble } from "./session-
37
38
  import { supportsVersionedSnapshots, writeTurnSentinel } from "./snapshot-protocol.js";
38
39
  import { LatestValuePublisher } from "./live-turn.js";
39
40
  const SYSTEM_AGENT_IDS = new Set(["pilotswarm", "sweeper", "resourcemgr", "facts-manager"]);
41
+ /** Same lineage principal for inline and durable agent selection. */
42
+ async function resolveCallerAgentOwnerKey(catalog, sessionId) {
43
+ const owner = catalog && sessionId
44
+ ? await resolveEffectiveSpawnOwner((id) => catalog.getSession(id), sessionId).catch(() => null)
45
+ : null;
46
+ return owner?.provider && owner?.subject ? `${owner.provider}\u0001${owner.subject}` : null;
47
+ }
40
48
  /**
41
49
  * THE agent-name resolver: FQN parsing, fuzzy matching, package privacy, and
42
50
  * owner shadowing in one place.
@@ -107,8 +115,10 @@ export async function resolveAgentDefinitionForCaller(opts) {
107
115
  const ownerKeyOf = (owner) => owner?.provider && owner?.subject ? `${owner.provider}\u0001${owner.subject}` : null;
108
116
  const visibleToCaller = async (agent) => {
109
117
  const agentOwnerKey = ownerKeyOf(agent?.packageOwner);
110
- if (agent?.packageScope !== "user" || !agentOwnerKey)
118
+ if (agent?.packageScope !== "user")
111
119
  return true;
120
+ if (!agentOwnerKey)
121
+ return false;
112
122
  const key = await callerOwnerKeyOnce();
113
123
  return key !== null && key === agentOwnerKey;
114
124
  };
@@ -172,6 +182,36 @@ export async function resolveAgentDefinitionForCaller(opts) {
172
182
  packageScope: agent.packageScope ?? undefined,
173
183
  };
174
184
  }
185
+ /** Legacy activity compatibility for frozen orchestrations. Not a spawn_agent selector. */
186
+ export async function resolveAgentDefinitionForRequiredToolForCaller(opts) {
187
+ const requiredTool = String(opts.requiredTool || "").trim();
188
+ if (!requiredTool)
189
+ return { status: "not_found", candidates: [] };
190
+ const declaresTool = (agent) => agent?.tools?.includes(requiredTool)
191
+ || agent?.copies?.some((copy) => copy?.tools?.includes(requiredTool));
192
+ const logicalNames = [...new Set((opts.userAgents ?? [])
193
+ .filter(declaresTool)
194
+ .map((agent) => String(agent?.name || "").trim())
195
+ .filter(Boolean))].sort((left, right) => left.localeCompare(right));
196
+ const resolved = new Map();
197
+ for (const agentName of logicalNames) {
198
+ const agent = await resolveAgentDefinitionForCaller({
199
+ agentName,
200
+ userAgents: opts.userAgents,
201
+ systemAgents: opts.systemAgents,
202
+ getCallerOwnerKey: opts.getCallerOwnerKey,
203
+ });
204
+ if (!agent || agent.creatable === false || !agent.tools?.includes(requiredTool))
205
+ continue;
206
+ resolved.set(agent.name, agent);
207
+ }
208
+ const candidates = [...resolved.keys()].sort((left, right) => left.localeCompare(right));
209
+ if (candidates.length === 0)
210
+ return { status: "not_found", candidates: [] };
211
+ if (candidates.length > 1)
212
+ return { status: "ambiguous", candidates };
213
+ return { status: "resolved", agent: resolved.get(candidates[0]), candidates };
214
+ }
175
215
  // The canvas helpers (filenames, slot normalization, revision derivation)
176
216
  // live in canvas-support.ts, shared with the app catalog. Re-exported so
177
217
  // existing importers keep their path.
@@ -521,15 +561,15 @@ function normalizeDistillerEffort(value) {
521
561
  function normalizeDistillerTier(value) {
522
562
  return value && DISTILLER_TIERS.has(value) ? value : undefined;
523
563
  }
524
- export function createSessionProxy(ctx, sessionId, affinityKey, config) {
564
+ export function createSessionProxy(ctx, sessionId, affinityKey, config, routingContract) {
525
565
  return {
526
566
  runTurn(prompt, bootstrap, turnIndex, turnMeta) {
527
- return ctx.scheduleActivityOnSession(
567
+ return routeHandoffActivity(ctx.scheduleActivityOnSession(
528
568
  // The epoch-start turn is a distinct activity name (runTurn2):
529
- // pre-1.0.67 workers don't register it, so a rolling deploy can
530
- // never hand the fresh-epoch create to a worker that would
531
- // silently resume the dead transcript instead.
532
- turnMeta?.epochStart ? "runTurn2" : "runTurn", {
569
+ // with an explicit contract since 1.0.67. New handoffs ALSO
570
+ // require a capability tag: activity names alone do not stop
571
+ // old workers from dequeuing work they cannot execute.
572
+ routedActivityName(turnMeta?.epochStart ? "runTurn2" : "runTurn", routingContract), {
533
573
  sessionId,
534
574
  prompt,
535
575
  config,
@@ -566,7 +606,7 @@ export function createSessionProxy(ctx, sessionId, affinityKey, config) {
566
606
  ...(turnMeta?.stashedPrompts && turnMeta.stashedPrompts.length > 0
567
607
  ? { stashedPrompts: turnMeta.stashedPrompts }
568
608
  : {}),
569
- }, affinityKey);
609
+ }, affinityKey), routingContract);
570
610
  },
571
611
  dehydrate(reason, eventData) {
572
612
  return ctx.scheduleActivityOnSession("dehydrateSession", {
@@ -734,7 +774,7 @@ export function bootstrapTurnOptions(requiredTool) {
734
774
  // ─── SessionManagerProxy ─────────────────────────────────────────
735
775
  // The orchestration's view of the SessionManager singleton.
736
776
  // Operations that don't require session affinity.
737
- export function createSessionManagerProxy(ctx) {
777
+ export function createSessionManagerProxy(ctx, routingContract, options) {
738
778
  return {
739
779
  listModels() {
740
780
  return ctx.scheduleActivity("listModels", {});
@@ -744,10 +784,10 @@ export function createSessionManagerProxy(ctx) {
744
784
  },
745
785
  /** Spawn a child session via the PilotSwarmClient SDK. Returns the generated child session ID. */
746
786
  spawnChildSession(parentSessionId, config, task, nestingLevel, isSystem, title, agentId, splash, titleIsExplicit, requiredTool) {
747
- return ctx.scheduleActivity("spawnChildSession", {
787
+ return routeHandoffActivity(ctx.scheduleActivity(routedActivityName("spawnChildSession", routingContract), {
748
788
  parentSessionId, config, task, nestingLevel, isSystem, title, agentId, splash, titleIsExplicit,
749
789
  ...(requiredTool ? { requiredTool } : {}),
750
- });
790
+ }), routingContract);
751
791
  },
752
792
  /**
753
793
  * Resolve a loaded agent config by name. Returns null if not found.
@@ -758,8 +798,18 @@ export function createSessionManagerProxy(ctx) {
758
798
  * the orchestration generator keeps the yield sequence byte-identical, so
759
799
  * this is not an orchestration version change.
760
800
  */
761
- resolveAgentConfig(agentName) {
762
- return ctx.scheduleActivity("resolveAgentConfig", { agentName, callerSessionId: ctx.instanceId });
801
+ resolveAgentConfig(agentName, callerSessionId, binding) {
802
+ return routeHandoffActivity(ctx.scheduleActivity(routedActivityName("resolveAgentConfig", routingContract), {
803
+ agentName,
804
+ callerSessionId: callerSessionId ?? ctx.instanceId,
805
+ ...(binding ? { binding } : {}),
806
+ }), routingContract);
807
+ },
808
+ resolveAgentForRequiredTool(requiredTool, callerSessionId) {
809
+ return routeHandoffActivity(ctx.scheduleActivity(routedActivityName("resolveAgentForRequiredTool", routingContract), {
810
+ requiredTool,
811
+ callerSessionId: callerSessionId ?? ctx.instanceId,
812
+ }), routingContract);
763
813
  },
764
814
  /** Send a message to a session via the PilotSwarmClient SDK. */
765
815
  sendToSession(sessionId, message) {
@@ -771,6 +821,9 @@ export function createSessionManagerProxy(ctx) {
771
821
  },
772
822
  /** Get the status of a session via the PilotSwarmClient SDK. */
773
823
  getSessionStatus(sessionId) {
824
+ if (options?.childResultProvenance) {
825
+ return routeHandoffActivity(ctx.scheduleActivity(HANDOFF_ACTIVITY_NAMES.getSessionStatus, { sessionId }), routingContract);
826
+ }
774
827
  return ctx.scheduleActivity("getSessionStatus", { sessionId });
775
828
  },
776
829
  /** Get orchestration runtime stats for a session. */
@@ -783,6 +836,9 @@ export function createSessionManagerProxy(ctx) {
783
836
  },
784
837
  /** List direct child sessions of a session. */
785
838
  listChildSessions(parentSessionId) {
839
+ if (options?.childResultProvenance) {
840
+ return routeHandoffActivity(ctx.scheduleActivity(HANDOFF_ACTIVITY_NAMES.listChildSessions, { parentSessionId }), routingContract);
841
+ }
786
842
  return ctx.scheduleActivity("listChildSessions", { parentSessionId });
787
843
  },
788
844
  /** @deprecated Send a child_updates event to a parent orchestration. Use sendToSession instead. */
@@ -1367,18 +1423,12 @@ artifactStore) {
1367
1423
  // previous inline copy had none of that: it could hand another user's
1368
1424
  // private agent to this session and could not address the shared copy
1369
1425
  // of a shadowed name.
1426
+ const getCallerOwnerKeyInline = () => resolveCallerAgentOwnerKey(catalog, input.sessionId);
1370
1427
  const resolveAgentConfigInline = (agentName) => resolveAgentDefinitionForCaller({
1371
1428
  agentName,
1372
1429
  userAgents,
1373
1430
  systemAgents,
1374
- getCallerOwnerKey: async () => {
1375
- const owner = catalog
1376
- ? await resolveEffectiveSpawnOwner((id) => catalog.getSession(id), input.sessionId).catch(() => null)
1377
- : null;
1378
- return owner?.provider && owner?.subject
1379
- ? `${owner.provider}\u0001${owner.subject}`
1380
- : null;
1381
- },
1431
+ getCallerOwnerKey: getCallerOwnerKeyInline,
1382
1432
  });
1383
1433
  const loadDirectChildSessions = async () => {
1384
1434
  const sdkClient = await getInlineClient();
@@ -1664,15 +1714,18 @@ artifactStore) {
1664
1714
  nestingLevel: 0,
1665
1715
  ...(normalizedModel ? { model: normalizedModel } : {}),
1666
1716
  ...(args.reasoning_effort ? { reasoningEffort: args.reasoning_effort } : {}),
1667
- boundAgentName: agentDef.name,
1717
+ boundAgentName: !agentDef.packageId && agentDef.namespace ? `${agentDef.namespace}:${agentDef.name}` : agentDef.name,
1718
+ ...(agentDef.packageId ? { boundAgentPackageId: agentDef.packageId } : {}),
1719
+ ...(!agentDef.packageId ? { boundAgentSource: "deployment" } : {}),
1720
+ namedAgentToolAdditions: [],
1668
1721
  promptLayering: { kind: "app-agent" },
1669
1722
  ...(agentDef.tools ? { toolNames: agentDef.tools } : {}),
1670
- agentId: agentDef.id ?? agentName,
1723
+ agentId: agentDef.id ?? agentDef.name,
1671
1724
  ...(owner ? { owner } : {}),
1672
1725
  });
1673
1726
  if (catalog) {
1674
1727
  const meta = {
1675
- agentId: agentDef.id ?? agentName,
1728
+ agentId: agentDef.id ?? agentDef.name,
1676
1729
  title: typeof args.title === "string" && args.title.trim()
1677
1730
  ? args.title.trim()
1678
1731
  : `${agentDef.title || agentName}: ${newSessionId.slice(0, 8)}`,
@@ -1716,6 +1769,9 @@ artifactStore) {
1716
1769
  },
1717
1770
  spawnAgent: async (args) => {
1718
1771
  try {
1772
+ if (Object.hasOwn(args, "required_tool") || Object.hasOwn(args, "requiredTool")) {
1773
+ return `[SYSTEM: spawn_agent failed — required_tool is no longer supported by spawn_agent. Use ps_list_agents to find a suitable named agent, then pass its exact agent_name and your assignment in task.]`;
1774
+ }
1719
1775
  const childNestingLevel = (input.nestingLevel ?? 0) + 1;
1720
1776
  if (childNestingLevel > MAX_NESTING_LEVEL) {
1721
1777
  return `[SYSTEM: spawn_agent failed — you are already at nesting level ${input.nestingLevel ?? 0} (max ${MAX_NESTING_LEVEL}). ` +
@@ -1741,24 +1797,24 @@ artifactStore) {
1741
1797
  let agentSplashMobile;
1742
1798
  let bootstrapRequiredTool;
1743
1799
  let boundAgentName;
1800
+ let boundAgentPackageId;
1744
1801
  let promptLayeringKind;
1745
1802
  let resolvedAgentName = args.agent_name;
1746
- const applyAgentDef = (agentDef, useDefinitionDefaults = false) => {
1747
- agentTask = useDefinitionDefaults
1748
- ? (agentDef.initialPrompt || `You are the ${agentDef.name} agent. Begin your work.`)
1749
- : (args.task || agentDef.initialPrompt || `You are the ${agentDef.name} agent. Begin your work.`);
1750
- agentSystemMessage = useDefinitionDefaults ? undefined : args.system_message;
1751
- agentToolNames = useDefinitionDefaults
1752
- ? (agentDef.tools ?? undefined)
1753
- : (args.tool_names ?? agentDef.tools ?? undefined);
1803
+ const applyAgentDef = (agentDef) => {
1804
+ agentTask = args.task || agentDef.initialPrompt || `You are the ${agentDef.name} agent. Begin your work.`;
1805
+ agentSystemMessage = undefined;
1806
+ // Match durable spawning: no parent package tools when
1807
+ // the selected definition declares no extra tools.
1808
+ agentToolNames = agentDef.tools ?? [];
1754
1809
  agentIsSystem = agentDef.system ?? false;
1755
1810
  if (!agentTitleIsExplicit)
1756
1811
  agentTitle = agentDef.title;
1757
- agentId = agentDef.id ?? resolvedAgentName;
1812
+ agentId = agentDef.id ?? agentDef.name;
1758
1813
  agentSplash = agentDef.splash;
1759
1814
  agentSplashMobile = agentDef.splashMobile;
1760
1815
  bootstrapRequiredTool = agentDef.initialRequiredTool;
1761
- boundAgentName = agentDef.name;
1816
+ boundAgentName = !agentDef.packageId && agentDef.namespace ? `${agentDef.namespace}:${agentDef.name}` : agentDef.name;
1817
+ boundAgentPackageId = agentDef.packageId;
1762
1818
  promptLayeringKind = agentDef.promptLayerKind
1763
1819
  ?? (agentDef.system
1764
1820
  ? ((agentDef.namespace || "pilotswarm") === "pilotswarm"
@@ -1766,16 +1822,26 @@ artifactStore) {
1766
1822
  : "app-system-agent")
1767
1823
  : "app-agent");
1768
1824
  };
1825
+ let agentDef = null;
1769
1826
  if (resolvedAgentName) {
1770
- const agentDef = await resolveAgentConfigInline(resolvedAgentName);
1827
+ agentDef = await resolveAgentConfigInline(resolvedAgentName);
1771
1828
  if (!agentDef) {
1772
1829
  return `[SYSTEM: spawn_agent failed — agent "${resolvedAgentName}" not found. Use ps_list_agents to see available agents.]`;
1773
1830
  }
1831
+ }
1832
+ if (agentDef) {
1774
1833
  if (agentDef.system && agentDef.creatable === false) {
1775
1834
  return `[SYSTEM: spawn_agent failed — agent "${resolvedAgentName}" is a worker-managed system agent and cannot be spawned from a session. ` +
1776
1835
  `If it is missing, the workers likely need to be restarted.]`;
1777
1836
  }
1778
- applyAgentDef(agentDef, resolvedAgentName !== args.agent_name);
1837
+ if (args.tool_names !== undefined) {
1838
+ return `[SYSTEM: spawn_agent failed — tool_names cannot override a bound named-agent definition. Use a custom task without agent_name, or remove tool_names.]`;
1839
+ }
1840
+ if (args.system_message !== undefined) {
1841
+ return `[SYSTEM: spawn_agent failed — system_message cannot override a bound named-agent definition. Put the bounded assignment in task instead.]`;
1842
+ }
1843
+ // The named definition owns its startup requirement.
1844
+ applyAgentDef(agentDef);
1779
1845
  }
1780
1846
  // Spawned children inherit the parent lineage's EFFECTIVE
1781
1847
  // owner instead of any system flag: the nearest owned
@@ -1803,14 +1869,18 @@ artifactStore) {
1803
1869
  // still apply. The parent is responsible for closing
1804
1870
  // each instance with complete_agent / cancel_agent /
1805
1871
  // delete_agent when it no longer needs the child.
1806
- const { boundAgentName: _parentBoundAgentName, promptLayering: _parentPromptLayering, isCrawler: _parentIsCrawler, isHarvester: _parentIsHarvester, ...parentConfig } = input.config;
1872
+ const { boundAgentName: _parentBoundAgentName, boundAgentPackageId: _parentBoundAgentPackageId, boundAgentSource: _parentBoundAgentSource, namedAgentToolAdditions: _parentNamedAgentToolAdditions, childContract: _parentChildContract, detachedPackageToolPolicy: _parentDetachedPackageToolPolicy, promptLayering: _parentPromptLayering, agentIdentity: _parentAgentIdentity, isCrawler: _parentIsCrawler, isHarvester: _parentIsHarvester, ...parentConfig } = input.config;
1807
1873
  const childConfig = {
1808
1874
  ...parentConfig,
1875
+ ...(boundAgentName ? { systemMessage: undefined } : {}),
1809
1876
  ...(agentModel ? { model: agentModel } : {}),
1810
1877
  ...(agentReasoningEffort ? { reasoningEffort: agentReasoningEffort } : {}),
1811
1878
  ...(args.context_tier !== undefined ? { contextTier: args.context_tier } : {}),
1812
1879
  ...(agentSystemMessage ? { systemMessage: agentSystemMessage } : {}),
1813
1880
  ...(boundAgentName ? { boundAgentName } : {}),
1881
+ ...(boundAgentPackageId ? { boundAgentPackageId } : {}),
1882
+ ...(boundAgentName && !boundAgentPackageId ? { boundAgentSource: "deployment" } : {}),
1883
+ detachedPackageToolPolicy: boundAgentName || args.tool_names?.length ? "reject" : "drop",
1814
1884
  ...(promptLayeringKind ? { promptLayering: { kind: promptLayeringKind } } : {}),
1815
1885
  ...(agentToolNames ? { toolNames: agentToolNames } : {}),
1816
1886
  ...(args.contract ? { childContract: args.contract } : {}),
@@ -1850,6 +1920,9 @@ artifactStore) {
1850
1920
  ...childModelCreationOptions(childConfig),
1851
1921
  systemMessage: childConfig.systemMessage,
1852
1922
  boundAgentName: childConfig.boundAgentName,
1923
+ boundAgentPackageId: childConfig.boundAgentPackageId,
1924
+ boundAgentSource: childConfig.boundAgentSource,
1925
+ detachedPackageToolPolicy: childConfig.detachedPackageToolPolicy,
1853
1926
  promptLayering: childConfig.promptLayering,
1854
1927
  toolNames: childConfig.toolNames,
1855
1928
  waitThreshold: childConfig.waitThreshold,
@@ -2225,7 +2298,7 @@ artifactStore) {
2225
2298
  }
2226
2299
  const sdkClient = await getInlineClient();
2227
2300
  const cmdId = `done-inline-${Date.now()}`;
2228
- await sdkClient._getDuroxideClient().enqueueEvent(child.orchId, "messages", JSON.stringify({ type: "cmd", cmd: "done", id: cmdId, args: { reason: "Completed by parent" } }));
2301
+ await sdkClient._getDuroxideClient().enqueueEvent(child.orchId, "messages", JSON.stringify({ type: "cmd", cmd: "done", id: cmdId, args: { reason: "Completed by parent" }, requestedBy: input.sessionId }));
2229
2302
  return `[SYSTEM: Graceful completion requested for sub-agent ${child.orchId}. ` +
2230
2303
  `Use check_agents or wait_for_agents to observe final completion.]`;
2231
2304
  }
@@ -2256,7 +2329,7 @@ artifactStore) {
2256
2329
  }
2257
2330
  const sdkClient = await getInlineClient();
2258
2331
  const cmdId = `cancel-inline-${Date.now()}`;
2259
- await sdkClient._getDuroxideClient().enqueueEvent(child.orchId, "messages", JSON.stringify({ type: "cmd", cmd: "cancel", id: cmdId, args: { reason: args.reason ?? "Cancelled by parent" } }));
2332
+ await sdkClient._getDuroxideClient().enqueueEvent(child.orchId, "messages", JSON.stringify({ type: "cmd", cmd: "cancel", id: cmdId, args: { reason: args.reason ?? "Cancelled by parent" }, requestedBy: input.sessionId }));
2260
2333
  return `[SYSTEM: Graceful cancellation requested for sub-agent ${child.orchId}. ` +
2261
2334
  `Use check_agents or wait_for_agents to observe final termination.${args.reason ? ` Reason: ${args.reason}` : ""}]`;
2262
2335
  }
@@ -2273,7 +2346,7 @@ artifactStore) {
2273
2346
  return `[SYSTEM: Sub-agent ${child.orchId} has been deleted.${args.reason ? ` Reason: ${args.reason}` : ""}]`;
2274
2347
  }
2275
2348
  const cmdId = `delete-inline-${Date.now()}`;
2276
- await sdkClient._getDuroxideClient().enqueueEvent(child.orchId, "messages", JSON.stringify({ type: "cmd", cmd: "delete", id: cmdId, args: { reason: args.reason ?? "Deleted by parent" } }));
2349
+ await sdkClient._getDuroxideClient().enqueueEvent(child.orchId, "messages", JSON.stringify({ type: "cmd", cmd: "delete", id: cmdId, args: { reason: args.reason ?? "Deleted by parent" }, requestedBy: input.sessionId }));
2277
2350
  return `[SYSTEM: Graceful deletion requested for sub-agent ${child.orchId}. ` +
2278
2351
  `It will cancel its descendants first and then delete itself.${args.reason ? ` Reason: ${args.reason}` : ""}]`;
2279
2352
  }
@@ -2778,6 +2851,9 @@ artifactStore) {
2778
2851
  };
2779
2852
  const EPHEMERAL_TYPES = new Set([
2780
2853
  "assistant.live_tick",
2854
+ "session.native_tasks_tick",
2855
+ "session.background_tasks_changed",
2856
+ "native.session.background_tasks_changed",
2781
2857
  "assistant.message_delta",
2782
2858
  "assistant.streaming_delta",
2783
2859
  "assistant.reasoning_delta",
@@ -2808,6 +2884,12 @@ artifactStore) {
2808
2884
  const liveTurnPublisher = liveTurnEnabled
2809
2885
  ? new LatestValuePublisher((payload) => catalog.publishLive(input.sessionId, "turn", { snapshot: payload }, workerNodeId || ""), (error) => activityCtx.traceInfo(`[runTurn.live] publish failed for ${input.sessionId}: ${error?.message ?? error}`))
2810
2886
  : null;
2887
+ // Native task progress is independent of streaming assistant text.
2888
+ // This queue is intentionally never drained on the model path: a
2889
+ // stalled live-plane write must not hold the worker turn open.
2890
+ const nativeTasksPublisher = typeof catalog?.publishLive === "function"
2891
+ ? new LatestValuePublisher(payload => catalog.publishLive(input.sessionId, "native-tasks", { snapshot: { ...payload } }, workerNodeId || ""), error => activityCtx.traceInfo(`[runTurn.nativeTasks] publish failed for ${input.sessionId}: ${error?.message ?? error}`))
2892
+ : null;
2811
2893
  const onEvent = catalog
2812
2894
  ? (event) => {
2813
2895
  if (event.eventType === "assistant.live_tick") {
@@ -2815,6 +2897,10 @@ artifactStore) {
2815
2897
  liveTurnPublisher.enqueue(event.data);
2816
2898
  return;
2817
2899
  }
2900
+ if (event.eventType === "session.native_tasks_tick") {
2901
+ nativeTasksPublisher?.enqueue(event.data);
2902
+ return;
2903
+ }
2818
2904
  if (EPHEMERAL_TYPES.has(event.eventType))
2819
2905
  return;
2820
2906
  const persistedEvent = summarizeSdkSystemPromptEchoEvent(event.eventType === "session.input_required_started"
@@ -2874,7 +2960,11 @@ artifactStore) {
2874
2960
  // the wrapped promise so the post-turn barrier waits for the
2875
2961
  // retry to settle before emitting turn_completed.
2876
2962
  const writePromise = cmsRetryBestEffort(`runTurn.onEvent recordEvent ${persistedEvent.eventType} session=${input.sessionId}`, () => catalog.recordEvents(input.sessionId, [persistedEvent], workerNodeId), (msg) => activityCtx.traceInfo(msg));
2877
- trackEventWrite(writePromise);
2963
+ // Task summaries are a redundant UI projection. The
2964
+ // original tool/lifecycle events still use the barrier;
2965
+ // a stuck projection write must not delay turn commit.
2966
+ if (event.eventType !== "native.task_updated")
2967
+ trackEventWrite(writePromise);
2878
2968
  }
2879
2969
  : undefined;
2880
2970
  // Record the user prompt as a CMS event before running the turn.
@@ -3354,6 +3444,12 @@ artifactStore) {
3354
3444
  return finalTurnResult;
3355
3445
  }
3356
3446
  catch (err) {
3447
+ if (err instanceof PackageToolBindingError || err instanceof BoundAgentPackageUnavailableError) {
3448
+ const message = err.message || String(err);
3449
+ activityCtx.traceInfo(`[runTurn] deterministic package-tool binding failure: ${message}`);
3450
+ finalTurnResult = { type: "error", message, retryable: false };
3451
+ return finalTurnResult;
3452
+ }
3357
3453
  if (isSessionLockAcquireTimeoutError(err)) {
3358
3454
  const message = err.message || String(err);
3359
3455
  activityCtx.traceInfo(`[runTurn] ${message}`);
@@ -3410,11 +3506,10 @@ artifactStore) {
3410
3506
  }
3411
3507
  }
3412
3508
  };
3413
- runtime.registerActivity("runTurn", runTurnHandler);
3414
- // Session regeneration: the epoch-start turn dispatches under a NEW
3415
- // activity name so pre-1.0.67 workers — which would silently resume the
3416
- // dead transcript — structurally cannot receive it (deployment gate §4).
3417
- runtime.registerActivity("runTurn2", runTurnHandler);
3509
+ registerHandoffActivity(runtime, "runTurn", runTurnHandler);
3510
+ // Keep the historical epoch activity for replay. 1.0.75 uses a renamed,
3511
+ // capability-tagged alias; the tag filter performs actual worker routing.
3512
+ registerHandoffActivity(runtime, "runTurn2", runTurnHandler);
3418
3513
  // ── abortTurn ────────────────────────────────────────────
3419
3514
  // Stop-turn fast-path interrupt. Routed on the session affinity key so it
3420
3515
  // lands on the worker owning the warm ManagedSession and runs CONCURRENTLY
@@ -3802,11 +3897,16 @@ artifactStore) {
3802
3897
  // resolveAgentDefinitionForCaller — shared with the control bridge so
3803
3898
  // spawn_agent/create_agent_session and this activity can never disagree
3804
3899
  // about which agent a name means.
3805
- runtime.registerActivity("resolveAgentConfig", async (_activityCtx, input) => {
3900
+ registerHandoffActivity(runtime, "resolveAgentConfig", async (_activityCtx, input) => {
3901
+ // Top-level verification sessions already selected a package/deployment
3902
+ // copy at creation. Keep that selection through the startup resolver.
3903
+ // An unavailable pin yields no definition; it never falls back by name.
3904
+ const pinnedCandidates = (agents) => agents?.filter(agent => (!input.binding?.packageId || agent.packageId === input.binding.packageId)
3905
+ && (input.binding?.source !== "deployment" || (!agent.packageId && agent.packageScope == null)));
3806
3906
  return resolveAgentDefinitionForCaller({
3807
3907
  agentName: input.agentName,
3808
- userAgents,
3809
- systemAgents,
3908
+ userAgents: pinnedCandidates(userAgents),
3909
+ systemAgents: pinnedCandidates(systemAgents),
3810
3910
  // PACKAGE PRIVACY, enforced at RESOLUTION rather than at creation.
3811
3911
  //
3812
3912
  // Workers install every enabled package, including other users'
@@ -3823,15 +3923,15 @@ artifactStore) {
3823
3923
  //
3824
3924
  // Deployment-owned plugin agents carry no package owner and stay
3825
3925
  // public, exactly as before.
3826
- getCallerOwnerKey: async () => {
3827
- const row = input.callerSessionId
3828
- ? await catalog?.getSession(input.callerSessionId)
3829
- : null;
3830
- const owner = row?.owner;
3831
- return owner?.provider && owner?.subject
3832
- ? `${owner.provider}\u0001${owner.subject}`
3833
- : null;
3834
- },
3926
+ getCallerOwnerKey: () => resolveCallerAgentOwnerKey(catalog, input.callerSessionId),
3927
+ });
3928
+ });
3929
+ registerHandoffActivity(runtime, "resolveAgentForRequiredTool", async (_activityCtx, input) => {
3930
+ return resolveAgentDefinitionForRequiredToolForCaller({
3931
+ requiredTool: input.requiredTool,
3932
+ userAgents,
3933
+ systemAgents,
3934
+ getCallerOwnerKey: () => resolveCallerAgentOwnerKey(catalog, input.callerSessionId),
3835
3935
  });
3836
3936
  });
3837
3937
  // ── spawnChildSession ─────────────────────────────────────
@@ -3839,7 +3939,7 @@ artifactStore) {
3839
3939
  // System child agents with a stable agentId use a deterministic UUID.
3840
3940
  // Other child sessions use a random UUID.
3841
3941
  // Goes through the full SDK path: CMS registration + orchestration startup.
3842
- runtime.registerActivity("spawnChildSession", async (activityCtx, input) => {
3942
+ registerHandoffActivity(runtime, "spawnChildSession", async (activityCtx, input) => {
3843
3943
  const startedAt = Date.now();
3844
3944
  const trace = (message) => {
3845
3945
  activityCtx.traceInfo(`[spawnChildSession] +${Date.now() - startedAt}ms ${message}`);
@@ -3910,6 +4010,9 @@ artifactStore) {
3910
4010
  ...childModelCreationOptions(input.config),
3911
4011
  systemMessage: input.config.systemMessage,
3912
4012
  boundAgentName: input.config.boundAgentName,
4013
+ boundAgentPackageId: input.config.boundAgentPackageId,
4014
+ boundAgentSource: input.config.boundAgentSource,
4015
+ detachedPackageToolPolicy: input.config.detachedPackageToolPolicy,
3913
4016
  promptLayering: input.config.promptLayering,
3914
4017
  toolNames: input.config.toolNames,
3915
4018
  waitThreshold: input.config.waitThreshold,
@@ -3933,12 +4036,23 @@ artifactStore) {
3933
4036
  meta.agentId = input.agentId;
3934
4037
  if (input.splash)
3935
4038
  meta.splash = input.splash;
3936
- // Frozen orchestration versions don't thread splashMobile through
3937
- // the spawn input, so resolve it from the loaded agent definition.
4039
+ // Resolve mobile metadata through the same package pin and caller
4040
+ // visibility rules as the prompt/tools, including for older inputs
4041
+ // that carry only an agent id. A bare first match can expose another
4042
+ // user's copy when private and shared packages have the same name.
3938
4043
  if (input.agentId) {
3939
- const normalizeId = (value) => (value || "").toLowerCase().replace(/[^a-z0-9]+/g, "");
3940
- const lookup = normalizeId(input.agentId);
3941
- const agentDef = [...(userAgents ?? []), ...(systemAgents ?? [])].find((a) => [a.id, a.name].map(normalizeId).filter(Boolean).includes(lookup));
4044
+ const packageId = input.config.boundAgentPackageId;
4045
+ const fromBoundCopy = (agents) => packageId
4046
+ ? agents?.filter(a => a.packageId === packageId)
4047
+ : input.config.boundAgentSource === "deployment"
4048
+ ? agents?.filter(a => !a.packageId && a.packageScope == null)
4049
+ : agents;
4050
+ const agentDef = await resolveAgentDefinitionForCaller({
4051
+ agentName: input.config.boundAgentName ?? input.agentId,
4052
+ userAgents: fromBoundCopy(userAgents),
4053
+ systemAgents: fromBoundCopy(systemAgents),
4054
+ getCallerOwnerKey: () => resolveCallerAgentOwnerKey(catalog, input.parentSessionId),
4055
+ });
3942
4056
  if (agentDef?.splashMobile)
3943
4057
  meta.splashMobile = agentDef.splashMobile;
3944
4058
  }
@@ -4021,27 +4135,29 @@ artifactStore) {
4021
4135
  });
4022
4136
  // ── getSessionStatus ────────────────────────────────────
4023
4137
  // Gets the status of a session via the PilotSwarmClient SDK.
4024
- runtime.registerActivity("getSessionStatus", async (activityCtx, input) => {
4138
+ const getSessionStatus = async (activityCtx, input, includeResultSource = false) => {
4025
4139
  activityCtx.traceInfo(`[getSessionStatus] session=${input.sessionId}`);
4026
4140
  if (!storeUrl)
4027
4141
  throw new Error("No storeUrl — cannot create PilotSwarmClient");
4028
4142
  const sdkClient = new PilotSwarmClient(internalClientConfig());
4029
4143
  try {
4030
4144
  await sdkClient.start();
4031
- const info = await sdkClient._getSessionInfo(input.sessionId);
4145
+ const info = await sdkClient._getSessionInfo(input.sessionId, includeResultSource ? { includeResultSource: true } : undefined);
4032
4146
  return JSON.stringify({
4033
4147
  sessionId: info.sessionId,
4034
4148
  status: info.status,
4035
4149
  title: info.title,
4036
4150
  iterations: info.iterations,
4037
4151
  result: info.result,
4152
+ ...(includeResultSource && info.resultSource ? { resultSource: info.resultSource } : {}),
4038
4153
  error: info.error,
4039
4154
  });
4040
4155
  }
4041
4156
  finally {
4042
4157
  await sdkClient.stop();
4043
4158
  }
4044
- });
4159
+ };
4160
+ registerHandoffActivity(runtime, "getSessionStatus", getSessionStatus, (ctx, input) => getSessionStatus(ctx, input, true));
4045
4161
  // ── getOrchestrationStats ───────────────────────────────
4046
4162
  // Gets duroxide orchestration runtime stats for a session.
4047
4163
  runtime.registerActivity("getOrchestrationStats", async (activityCtx, input) => {
@@ -4084,7 +4200,7 @@ artifactStore) {
4084
4200
  });
4085
4201
  // ── listChildSessions ───────────────────────────────────
4086
4202
  // Lists direct child sessions of a parent with merged live status.
4087
- runtime.registerActivity("listChildSessions", async (activityCtx, input) => {
4203
+ const listChildSessions = async (activityCtx, input, includeResultSource = false) => {
4088
4204
  activityCtx.traceInfo(`[listChildSessions] parent=${input.parentSessionId}`);
4089
4205
  if (!storeUrl)
4090
4206
  throw new Error("No storeUrl — cannot create PilotSwarmClient");
@@ -4094,7 +4210,7 @@ artifactStore) {
4094
4210
  const sessions = await sdkClient.listSessions();
4095
4211
  const directChildren = sessions.filter(s => s.parentSessionId === input.parentSessionId);
4096
4212
  const enriched = await Promise.all(directChildren.map(async (child) => {
4097
- const info = await sdkClient._getSessionInfo(child.sessionId);
4213
+ const info = await sdkClient._getSessionInfo(child.sessionId, includeResultSource ? { includeResultSource: true } : undefined);
4098
4214
  const outcome = catalog ? await catalog.getChildOutcome(child.sessionId).catch(() => null) : null;
4099
4215
  const outcomeResult = normalizeJsonObject(outcome?.resultJson?.current);
4100
4216
  const contractCurrent = normalizeJsonObject(outcome?.contractJson?.current);
@@ -4108,6 +4224,10 @@ artifactStore) {
4108
4224
  isSystem: child.isSystem ?? info.isSystem ?? false,
4109
4225
  agentId: child.agentId ?? info.agentId,
4110
4226
  result: outcome?.summary ?? (typeof outcomeResult?.summary === "string" ? outcomeResult.summary : info.result),
4227
+ ...(includeResultSource ? {
4228
+ resultSource: outcome?.summary != null || typeof outcomeResult?.summary === "string"
4229
+ ? "child_outcome" : info.resultSource,
4230
+ } : {}),
4111
4231
  contract: contractCurrent ?? undefined,
4112
4232
  contractStatus: outcome?.contractJson ? "contracted" : undefined,
4113
4233
  verdict: outcome?.verdict ?? undefined,
@@ -4120,7 +4240,8 @@ artifactStore) {
4120
4240
  finally {
4121
4241
  await sdkClient.stop();
4122
4242
  }
4123
- });
4243
+ };
4244
+ registerHandoffActivity(runtime, "listChildSessions", listChildSessions, (ctx, input) => listChildSessions(ctx, input, true));
4124
4245
  // ── notifyParent ────────────────────────────────────────
4125
4246
  // Sends a child_updates event to the parent orchestration so it can
4126
4247
  // wake up from durable sleep and process the child's result.