pilotswarm-sdk 0.5.64 → 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 (231) hide show
  1. package/dist/activity-routing.d.ts +21 -0
  2. package/dist/activity-routing.d.ts.map +1 -0
  3. package/dist/activity-routing.js +32 -0
  4. package/dist/activity-routing.js.map +1 -0
  5. package/dist/agent-discovery.d.ts +35 -0
  6. package/dist/agent-discovery.d.ts.map +1 -0
  7. package/dist/agent-discovery.js +107 -0
  8. package/dist/agent-discovery.js.map +1 -0
  9. package/dist/client.d.ts +9 -1
  10. package/dist/client.d.ts.map +1 -1
  11. package/dist/client.js +94 -12
  12. package/dist/client.js.map +1 -1
  13. package/dist/managed-session.d.ts.map +1 -1
  14. package/dist/managed-session.js +21 -13
  15. package/dist/managed-session.js.map +1 -1
  16. package/dist/native-subagents.d.ts +1 -1
  17. package/dist/native-subagents.d.ts.map +1 -1
  18. package/dist/native-subagents.js +11 -6
  19. package/dist/native-subagents.js.map +1 -1
  20. package/dist/orchestration/agents.d.ts +8 -3
  21. package/dist/orchestration/agents.d.ts.map +1 -1
  22. package/dist/orchestration/agents.js +87 -36
  23. package/dist/orchestration/agents.js.map +1 -1
  24. package/dist/orchestration/index.d.ts +2 -2
  25. package/dist/orchestration/index.js +1 -1
  26. package/dist/orchestration/lifecycle.js +1 -1
  27. package/dist/orchestration/lifecycle.js.map +1 -1
  28. package/dist/orchestration/runtime.d.ts +1 -1
  29. package/dist/orchestration/runtime.d.ts.map +1 -1
  30. package/dist/orchestration/runtime.js +18 -4
  31. package/dist/orchestration/runtime.js.map +1 -1
  32. package/dist/orchestration/turn.d.ts.map +1 -1
  33. package/dist/orchestration/turn.js +3 -5
  34. package/dist/orchestration/turn.js.map +1 -1
  35. package/dist/orchestration-registry.d.ts.map +1 -1
  36. package/dist/orchestration-registry.js +12 -2
  37. package/dist/orchestration-registry.js.map +1 -1
  38. package/dist/orchestration-version.d.ts +1 -1
  39. package/dist/orchestration-version.js +1 -1
  40. package/dist/orchestration.d.ts +2 -2
  41. package/dist/orchestration.js +1 -1
  42. package/dist/orchestration_1_0_46.d.ts +1 -1
  43. package/dist/orchestration_1_0_47.d.ts +1 -1
  44. package/dist/orchestration_1_0_48.d.ts +1 -1
  45. package/dist/orchestration_1_0_49.d.ts +1 -1
  46. package/dist/orchestration_1_0_50.d.ts +1 -1
  47. package/dist/orchestration_1_0_73/agents.d.ts +61 -0
  48. package/dist/orchestration_1_0_73/agents.d.ts.map +1 -0
  49. package/dist/orchestration_1_0_73/agents.js +843 -0
  50. package/dist/orchestration_1_0_73/agents.js.map +1 -0
  51. package/dist/orchestration_1_0_73/index.d.ts +24 -0
  52. package/dist/orchestration_1_0_73/index.d.ts.map +1 -0
  53. package/dist/orchestration_1_0_73/index.js +13 -0
  54. package/dist/orchestration_1_0_73/index.js.map +1 -0
  55. package/dist/orchestration_1_0_73/lifecycle.d.ts +51 -0
  56. package/dist/orchestration_1_0_73/lifecycle.d.ts.map +1 -0
  57. package/dist/orchestration_1_0_73/lifecycle.js +981 -0
  58. package/dist/orchestration_1_0_73/lifecycle.js.map +1 -0
  59. package/dist/orchestration_1_0_73/queue.d.ts +20 -0
  60. package/dist/orchestration_1_0_73/queue.d.ts.map +1 -0
  61. package/dist/orchestration_1_0_73/queue.js +894 -0
  62. package/dist/orchestration_1_0_73/queue.js.map +1 -0
  63. package/dist/orchestration_1_0_73/runtime.d.ts +31 -0
  64. package/dist/orchestration_1_0_73/runtime.d.ts.map +1 -0
  65. package/dist/orchestration_1_0_73/runtime.js +230 -0
  66. package/dist/orchestration_1_0_73/runtime.js.map +1 -0
  67. package/dist/orchestration_1_0_73/state.d.ts +214 -0
  68. package/dist/orchestration_1_0_73/state.d.ts.map +1 -0
  69. package/dist/orchestration_1_0_73/state.js +178 -0
  70. package/dist/orchestration_1_0_73/state.js.map +1 -0
  71. package/dist/orchestration_1_0_73/turn.d.ts +34 -0
  72. package/dist/orchestration_1_0_73/turn.d.ts.map +1 -0
  73. package/dist/orchestration_1_0_73/turn.js +1435 -0
  74. package/dist/orchestration_1_0_73/turn.js.map +1 -0
  75. package/dist/orchestration_1_0_73/utils.d.ts +39 -0
  76. package/dist/orchestration_1_0_73/utils.d.ts.map +1 -0
  77. package/dist/orchestration_1_0_73/utils.js +322 -0
  78. package/dist/orchestration_1_0_73/utils.js.map +1 -0
  79. package/dist/orchestration_1_0_74/agents.d.ts +61 -0
  80. package/dist/orchestration_1_0_74/agents.d.ts.map +1 -0
  81. package/dist/orchestration_1_0_74/agents.js +889 -0
  82. package/dist/orchestration_1_0_74/agents.js.map +1 -0
  83. package/dist/orchestration_1_0_74/index.d.ts +24 -0
  84. package/dist/orchestration_1_0_74/index.d.ts.map +1 -0
  85. package/dist/orchestration_1_0_74/index.js +13 -0
  86. package/dist/orchestration_1_0_74/index.js.map +1 -0
  87. package/dist/orchestration_1_0_74/lifecycle.d.ts +51 -0
  88. package/dist/orchestration_1_0_74/lifecycle.d.ts.map +1 -0
  89. package/dist/orchestration_1_0_74/lifecycle.js +981 -0
  90. package/dist/orchestration_1_0_74/lifecycle.js.map +1 -0
  91. package/dist/orchestration_1_0_74/queue.d.ts +20 -0
  92. package/dist/orchestration_1_0_74/queue.d.ts.map +1 -0
  93. package/dist/orchestration_1_0_74/queue.js +894 -0
  94. package/dist/orchestration_1_0_74/queue.js.map +1 -0
  95. package/dist/orchestration_1_0_74/runtime.d.ts +31 -0
  96. package/dist/orchestration_1_0_74/runtime.d.ts.map +1 -0
  97. package/dist/orchestration_1_0_74/runtime.js +232 -0
  98. package/dist/orchestration_1_0_74/runtime.js.map +1 -0
  99. package/dist/orchestration_1_0_74/state.d.ts +214 -0
  100. package/dist/orchestration_1_0_74/state.d.ts.map +1 -0
  101. package/dist/orchestration_1_0_74/state.js +178 -0
  102. package/dist/orchestration_1_0_74/state.js.map +1 -0
  103. package/dist/orchestration_1_0_74/turn.d.ts +34 -0
  104. package/dist/orchestration_1_0_74/turn.d.ts.map +1 -0
  105. package/dist/orchestration_1_0_74/turn.js +1435 -0
  106. package/dist/orchestration_1_0_74/turn.js.map +1 -0
  107. package/dist/orchestration_1_0_74/utils.d.ts +39 -0
  108. package/dist/orchestration_1_0_74/utils.d.ts.map +1 -0
  109. package/dist/orchestration_1_0_74/utils.js +322 -0
  110. package/dist/orchestration_1_0_74/utils.js.map +1 -0
  111. package/dist/orchestration_1_0_75/agents.d.ts +61 -0
  112. package/dist/orchestration_1_0_75/agents.d.ts.map +1 -0
  113. package/dist/orchestration_1_0_75/agents.js +887 -0
  114. package/dist/orchestration_1_0_75/agents.js.map +1 -0
  115. package/dist/orchestration_1_0_75/index.d.ts +24 -0
  116. package/dist/orchestration_1_0_75/index.d.ts.map +1 -0
  117. package/dist/orchestration_1_0_75/index.js +13 -0
  118. package/dist/orchestration_1_0_75/index.js.map +1 -0
  119. package/dist/orchestration_1_0_75/lifecycle.d.ts +51 -0
  120. package/dist/orchestration_1_0_75/lifecycle.d.ts.map +1 -0
  121. package/dist/orchestration_1_0_75/lifecycle.js +981 -0
  122. package/dist/orchestration_1_0_75/lifecycle.js.map +1 -0
  123. package/dist/orchestration_1_0_75/queue.d.ts +20 -0
  124. package/dist/orchestration_1_0_75/queue.d.ts.map +1 -0
  125. package/dist/orchestration_1_0_75/queue.js +894 -0
  126. package/dist/orchestration_1_0_75/queue.js.map +1 -0
  127. package/dist/orchestration_1_0_75/runtime.d.ts +31 -0
  128. package/dist/orchestration_1_0_75/runtime.d.ts.map +1 -0
  129. package/dist/orchestration_1_0_75/runtime.js +239 -0
  130. package/dist/orchestration_1_0_75/runtime.js.map +1 -0
  131. package/dist/orchestration_1_0_75/state.d.ts +214 -0
  132. package/dist/orchestration_1_0_75/state.d.ts.map +1 -0
  133. package/dist/orchestration_1_0_75/state.js +178 -0
  134. package/dist/orchestration_1_0_75/state.js.map +1 -0
  135. package/dist/orchestration_1_0_75/turn.d.ts +34 -0
  136. package/dist/orchestration_1_0_75/turn.d.ts.map +1 -0
  137. package/dist/orchestration_1_0_75/turn.js +1435 -0
  138. package/dist/orchestration_1_0_75/turn.js.map +1 -0
  139. package/dist/orchestration_1_0_75/utils.d.ts +39 -0
  140. package/dist/orchestration_1_0_75/utils.d.ts.map +1 -0
  141. package/dist/orchestration_1_0_75/utils.js +322 -0
  142. package/dist/orchestration_1_0_75/utils.js.map +1 -0
  143. package/dist/orchestration_1_0_76/agents.d.ts +61 -0
  144. package/dist/orchestration_1_0_76/agents.d.ts.map +1 -0
  145. package/dist/orchestration_1_0_76/agents.js +865 -0
  146. package/dist/orchestration_1_0_76/agents.js.map +1 -0
  147. package/dist/orchestration_1_0_76/index.d.ts +24 -0
  148. package/dist/orchestration_1_0_76/index.d.ts.map +1 -0
  149. package/dist/orchestration_1_0_76/index.js +13 -0
  150. package/dist/orchestration_1_0_76/index.js.map +1 -0
  151. package/dist/orchestration_1_0_76/lifecycle.d.ts +51 -0
  152. package/dist/orchestration_1_0_76/lifecycle.d.ts.map +1 -0
  153. package/dist/orchestration_1_0_76/lifecycle.js +981 -0
  154. package/dist/orchestration_1_0_76/lifecycle.js.map +1 -0
  155. package/dist/orchestration_1_0_76/queue.d.ts +20 -0
  156. package/dist/orchestration_1_0_76/queue.d.ts.map +1 -0
  157. package/dist/orchestration_1_0_76/queue.js +894 -0
  158. package/dist/orchestration_1_0_76/queue.js.map +1 -0
  159. package/dist/orchestration_1_0_76/runtime.d.ts +31 -0
  160. package/dist/orchestration_1_0_76/runtime.d.ts.map +1 -0
  161. package/dist/orchestration_1_0_76/runtime.js +239 -0
  162. package/dist/orchestration_1_0_76/runtime.js.map +1 -0
  163. package/dist/orchestration_1_0_76/state.d.ts +214 -0
  164. package/dist/orchestration_1_0_76/state.d.ts.map +1 -0
  165. package/dist/orchestration_1_0_76/state.js +178 -0
  166. package/dist/orchestration_1_0_76/state.js.map +1 -0
  167. package/dist/orchestration_1_0_76/turn.d.ts +34 -0
  168. package/dist/orchestration_1_0_76/turn.d.ts.map +1 -0
  169. package/dist/orchestration_1_0_76/turn.js +1435 -0
  170. package/dist/orchestration_1_0_76/turn.js.map +1 -0
  171. package/dist/orchestration_1_0_76/utils.d.ts +39 -0
  172. package/dist/orchestration_1_0_76/utils.d.ts.map +1 -0
  173. package/dist/orchestration_1_0_76/utils.js +322 -0
  174. package/dist/orchestration_1_0_76/utils.js.map +1 -0
  175. package/dist/orchestration_1_0_77/agents.d.ts +66 -0
  176. package/dist/orchestration_1_0_77/agents.d.ts.map +1 -0
  177. package/dist/orchestration_1_0_77/agents.js +895 -0
  178. package/dist/orchestration_1_0_77/agents.js.map +1 -0
  179. package/dist/orchestration_1_0_77/index.d.ts +24 -0
  180. package/dist/orchestration_1_0_77/index.d.ts.map +1 -0
  181. package/dist/orchestration_1_0_77/index.js +13 -0
  182. package/dist/orchestration_1_0_77/index.js.map +1 -0
  183. package/dist/orchestration_1_0_77/lifecycle.d.ts +51 -0
  184. package/dist/orchestration_1_0_77/lifecycle.d.ts.map +1 -0
  185. package/dist/orchestration_1_0_77/lifecycle.js +981 -0
  186. package/dist/orchestration_1_0_77/lifecycle.js.map +1 -0
  187. package/dist/orchestration_1_0_77/queue.d.ts +20 -0
  188. package/dist/orchestration_1_0_77/queue.d.ts.map +1 -0
  189. package/dist/orchestration_1_0_77/queue.js +894 -0
  190. package/dist/orchestration_1_0_77/queue.js.map +1 -0
  191. package/dist/orchestration_1_0_77/runtime.d.ts +31 -0
  192. package/dist/orchestration_1_0_77/runtime.d.ts.map +1 -0
  193. package/dist/orchestration_1_0_77/runtime.js +239 -0
  194. package/dist/orchestration_1_0_77/runtime.js.map +1 -0
  195. package/dist/orchestration_1_0_77/state.d.ts +214 -0
  196. package/dist/orchestration_1_0_77/state.d.ts.map +1 -0
  197. package/dist/orchestration_1_0_77/state.js +178 -0
  198. package/dist/orchestration_1_0_77/state.js.map +1 -0
  199. package/dist/orchestration_1_0_77/turn.d.ts +34 -0
  200. package/dist/orchestration_1_0_77/turn.d.ts.map +1 -0
  201. package/dist/orchestration_1_0_77/turn.js +1433 -0
  202. package/dist/orchestration_1_0_77/turn.js.map +1 -0
  203. package/dist/orchestration_1_0_77/utils.d.ts +39 -0
  204. package/dist/orchestration_1_0_77/utils.d.ts.map +1 -0
  205. package/dist/orchestration_1_0_77/utils.js +322 -0
  206. package/dist/orchestration_1_0_77/utils.js.map +1 -0
  207. package/dist/reserved-tool-names.d.ts +5 -0
  208. package/dist/reserved-tool-names.d.ts.map +1 -0
  209. package/dist/reserved-tool-names.js +102 -0
  210. package/dist/reserved-tool-names.js.map +1 -0
  211. package/dist/session-manager.d.ts +25 -1
  212. package/dist/session-manager.d.ts.map +1 -1
  213. package/dist/session-manager.js +275 -93
  214. package/dist/session-manager.js.map +1 -1
  215. package/dist/session-proxy.d.ts +28 -3
  216. package/dist/session-proxy.d.ts.map +1 -1
  217. package/dist/session-proxy.js +174 -70
  218. package/dist/session-proxy.js.map +1 -1
  219. package/dist/session-store.d.ts +2 -0
  220. package/dist/session-store.d.ts.map +1 -1
  221. package/dist/session-store.js +18 -2
  222. package/dist/session-store.js.map +1 -1
  223. package/dist/types.d.ts +17 -3
  224. package/dist/types.d.ts.map +1 -1
  225. package/dist/types.js.map +1 -1
  226. package/dist/worker.d.ts +9 -3
  227. package/dist/worker.d.ts.map +1 -1
  228. package/dist/worker.js +110 -99
  229. package/dist/worker.js.map +1 -1
  230. package/package.json +4 -3
  231. package/plugins/system/agents/default.agent.md +4 -3
package/dist/worker.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { AGENT_HANDOFF_CAPABILITY } from "./activity-routing.js";
1
2
  import { resolveNativeSubagents } from "./native-subagents.js";
2
3
  import { FeatureFlagCache } from "./feature-flag-cache.js";
3
4
  import { SessionManager, packageAgentKey, agentOwnerKey } from "./session-manager.js";
@@ -6,7 +7,8 @@ import { createSessionBlobStore } from "./blob-store.js";
6
7
  import { FilesystemArtifactStore, FilesystemSessionStore } from "./session-store.js";
7
8
  import { registerActivities } from "./session-proxy.js";
8
9
  import { DURABLE_SESSION_ORCHESTRATION_NAME, DURABLE_SESSION_ORCHESTRATION_REGISTRY, } from "./orchestration-registry.js";
9
- import { PgSessionCatalog } from "./cms.js";
10
+ import { PgSessionCatalog, resolveEffectiveSpawnOwner } from "./cms.js";
11
+ import { createAgentDiscoveryTool } from "./agent-discovery.js";
10
12
  import { loadAgentFiles, validateAgentDefinition } from "./agent-loader.js";
11
13
  import { clipDescription, composeDeclaredSkillsPrompt, loadSkillsSync } from "./skills.js";
12
14
  import { resolveSystemAgentSessionPlans, startSystemAgents } from "./system-agents.js";
@@ -22,8 +24,8 @@ import { createSweeperTools } from "./sweeper-tools.js";
22
24
  import { createResourceManagerTools } from "./resourcemgr-tools.js";
23
25
  import { composeSystemPrompt, mergePromptSections } from "./prompt-layering.js";
24
26
  import { buildSchemaIdentifier } from "./prompt-layers.js";
25
- import { DEFAULT_TURN_TIMEOUT_MS } from "./managed-session.js";
26
- import { defineTool } from "@github/copilot-sdk";
27
+ import { DEFAULT_TURN_TIMEOUT_MS, ManagedSession } from "./managed-session.js";
28
+ import { findReservedPackageToolName } from "./reserved-tool-names.js";
27
29
  import { installAgentPackages, loadAgentPackageTools } from "./agent-package-installer.js";
28
30
  import fs from "node:fs";
29
31
  import os from "node:os";
@@ -185,6 +187,9 @@ export class PilotSwarmWorker {
185
187
  /** Mtime watcher that re-loads model_providers.json on file change. */
186
188
  _modelProvidersReloader = null;
187
189
  _modelProvidersReloadTimer = null;
190
+ /** Close admission when drain begins; _started stays true until teardown ends. */
191
+ _providerReconciliationEnabled = false;
192
+ _providerReconciliation = null;
188
193
  /** Embedded PilotSwarm framework prompt. */
189
194
  _frameworkBasePrompt = null;
190
195
  /** Tool names declared by the embedded PilotSwarm framework default agent. */
@@ -322,12 +327,34 @@ export class PilotSwarmWorker {
322
327
  turnInactivityTimeoutMs: options.turnInactivityTimeoutMs,
323
328
  }, effectiveSessionStateDir);
324
329
  this.sessionManager.setModelProvidersRefresher(() => this._refreshProviderRegistry());
330
+ }
331
+ _startProviderPolling() {
332
+ this._providerReconciliationEnabled = true;
325
333
  // Poll for model_providers.json changes (30s, unref'd so it never
326
334
  // holds the process open). On reload, swap the worker's registry AND
327
335
  // the SessionManager's — new sessions and per-turn model resolution
328
336
  // pick up the fresh catalog immediately.
329
- if (this._modelProvidersReloader?.path || this._modelProviders) {
337
+ if (!this._modelProvidersReloadTimer && (this._modelProvidersReloader?.path || this._modelProviders)) {
330
338
  this._modelProvidersReloadTimer = setInterval(() => {
339
+ this._reconcileProvidersAndSystemAgents(true);
340
+ }, 30_000);
341
+ this._modelProvidersReloadTimer.unref?.();
342
+ }
343
+ }
344
+ _stopProviderPolling() {
345
+ this._providerReconciliationEnabled = false;
346
+ if (this._modelProvidersReloadTimer) {
347
+ clearInterval(this._modelProvidersReloadTimer);
348
+ this._modelProvidersReloadTimer = null;
349
+ }
350
+ }
351
+ _reconcileProvidersAndSystemAgents(refreshProviders) {
352
+ // Initial bootstrap and periodic reconciliation share one task. A slow
353
+ // catalog must not accumulate overlapping refreshes or agent starts.
354
+ if (!this._providerReconciliationEnabled || this._providerReconciliation)
355
+ return;
356
+ this._providerReconciliation = (async () => {
357
+ if (refreshProviders) {
331
358
  if (this._modelProvidersReloader?.checkAndReload()) {
332
359
  this._modelProviders = this._modelProvidersReloader.current;
333
360
  this._modelProviderTypes = this._modelProvidersReloader.types;
@@ -338,12 +365,13 @@ export class PilotSwarmWorker {
338
365
  // catalog is re-read on the same tick as the file. Without
339
366
  // it a provider somebody just added would resolve no
340
367
  // credential until the worker restarted.
341
- void this._refreshProviderRegistry()
342
- .then(() => this._startSystemAgents())
343
- .catch((err) => console.warn(`[PilotSwarmWorker] provider/system reconciliation failed: ${String(err?.message ?? err)}`));
344
- }, 30_000);
345
- this._modelProvidersReloadTimer.unref?.();
346
- }
368
+ await this._refreshProviderRegistry();
369
+ }
370
+ if (this._providerReconciliationEnabled)
371
+ await this._startSystemAgents();
372
+ })()
373
+ .catch((err) => console.warn(`[PilotSwarmWorker] provider/system reconciliation failed: ${String(err?.message ?? err)}`))
374
+ .finally(() => { this._providerReconciliation = null; });
347
375
  }
348
376
  /**
349
377
  * Rebuild what the SessionManager resolves models against: the TYPES
@@ -668,6 +696,7 @@ export class PilotSwarmWorker {
668
696
  const inspectClient = new Client(this._provider);
669
697
  this.sessionManager.setDuroxideClient(inspectClient);
670
698
  const runtimeOptions = {
699
+ workerTagFilter: { defaultAnd: [AGENT_HANDOFF_CAPABILITY] },
671
700
  orchestrationConcurrency,
672
701
  workerConcurrency,
673
702
  dispatcherPollIntervalMs: 10,
@@ -749,65 +778,18 @@ export class PilotSwarmWorker {
749
778
  });
750
779
  this.registerTools(rmTools);
751
780
  }
752
- // ps_list_agents tool — exposes user-creatable agents by default.
753
- // NOTE: prefixed with `ps_` to avoid collision with the Copilot SDK's
754
- // built-in `list_agents` tool (introduced in @github/copilot 1.0.32),
755
- // which lists live background-agent task instances rather than blueprints.
756
- const listAgentsTool = defineTool("ps_list_agents", {
757
- description: "List all available agent BLUEPRINTS (definitions loaded from .agent.md files). " +
758
- "By default this returns only user-creatable named agents. " +
759
- "Worker-managed system agents are hidden from the default list because they are NOT valid spawn_agent targets. " +
760
- "Pass systemOnly=true only when you need to inspect system-agent definitions for diagnostics. " +
761
- "Use this to discover what agents CAN be spawned. To check status of sub-agents you ALREADY spawned, use check_agents instead. " +
762
- "IMPORTANT: Do NOT call this unless you actually need to spawn an agent and don't know its name. " +
763
- "Seeing an agent in this list does NOT mean you should spawn it.",
764
- parameters: {
765
- type: "object",
766
- properties: {
767
- systemOnly: {
768
- type: "boolean",
769
- description: "If true, only return system agents. Default: false",
770
- },
771
- creatableOnly: {
772
- type: "boolean",
773
- description: "If true, only return user-creatable (non-system) agents. This matches the default behavior.",
774
- },
775
- },
776
- },
777
- handler: async (args) => {
778
- const allAgents = [
779
- ...this._loadedAgents.map(a => ({
780
- name: a.name,
781
- namespace: a.namespace || "custom",
782
- qualifiedName: `${a.namespace || "custom"}:${a.name}`,
783
- description: a.description || null,
784
- tools: a.tools || [],
785
- skills: a.skills || [],
786
- system: false,
787
- creatable: true,
788
- id: null,
789
- parent: null,
790
- })),
791
- ...this._loadedSystemAgents.map(a => ({
792
- name: a.name,
793
- namespace: a.namespace || "pilotswarm",
794
- qualifiedName: `${a.namespace || "pilotswarm"}:${a.name}`,
795
- description: a.description || null,
796
- tools: a.tools || [],
797
- system: true,
798
- creatable: false,
799
- id: a.id || null,
800
- parent: a.parent || null,
801
- })),
802
- ];
803
- let filtered = allAgents.filter(a => !a.system);
804
- if (args.systemOnly) {
805
- filtered = allAgents.filter(a => a.system);
806
- }
807
- else if (args.creatableOnly) {
808
- filtered = allAgents.filter(a => !a.system);
809
- }
810
- return JSON.stringify({ agents: filtered, total: filtered.length }, null, 2);
781
+ // ps_ avoids the Copilot CLI's native list_agents task-status tool.
782
+ // Listing uses the same owner and copy resolution as spawn_agent.
783
+ const listAgentsTool = createAgentDiscoveryTool({
784
+ // Same identities/owners/order as the raw spawn definitions,
785
+ // with MCP references already reduced to their admitted grants.
786
+ getUserAgents: () => this._loadedAgents,
787
+ getSystemAgents: () => this._loadedSystemAgents,
788
+ getCallerOwnerKey: async (sessionId) => {
789
+ if (!this._catalog || !sessionId)
790
+ return null;
791
+ const owner = await resolveEffectiveSpawnOwner((id) => this._catalog.getSession(id), sessionId);
792
+ return owner?.provider && owner?.subject ? `${owner.provider}\u0001${owner.subject}` : null;
811
793
  },
812
794
  });
813
795
  this.registerTools([listAgentsTool]);
@@ -815,6 +797,7 @@ export class PilotSwarmWorker {
815
797
  console.error("[PilotSwarmWorker] Runtime error:", err);
816
798
  });
817
799
  this._started = true;
800
+ this._startProviderPolling();
818
801
  // Autonomous eviction clock (lifecycle protocol §3.4): local session
819
802
  // state is a cache. Sessions idle past the hold window + margin are
820
803
  // reclaimed locally (committed → delete; legacy → dehydrate) with no
@@ -842,11 +825,11 @@ export class PilotSwarmWorker {
842
825
  // Auto-start system agents defined in plugins (idempotent), but do not
843
826
  // block worker.start() on the bootstrap race. The TUI should become
844
827
  // interactive even if first-run system-agent startup is slow.
845
- void this._startSystemAgents().catch((err) => {
846
- console.warn(`[PilotSwarmWorker] background system agent startup failed: ${err?.message ?? err}`);
847
- });
828
+ // Provider routing was refreshed above, before the runtime started.
829
+ this._reconcileProvidersAndSystemAgents(false);
848
830
  }
849
831
  async stop() {
832
+ this._stopProviderPolling();
850
833
  if (this._evictionTimer) {
851
834
  clearInterval(this._evictionTimer);
852
835
  this._evictionTimer = null;
@@ -868,6 +851,9 @@ export class PilotSwarmWorker {
868
851
  await this.runtime.shutdown(shutdownTimeoutMs);
869
852
  this.runtime = null;
870
853
  }
854
+ // Stop fetching first, then let any already-admitted bootstrap finish
855
+ // while the catalog/provider it uses are still open.
856
+ await this._providerReconciliation;
871
857
  await this.sessionManager.shutdown();
872
858
  if (this._catalog) {
873
859
  try {
@@ -915,6 +901,7 @@ export class PilotSwarmWorker {
915
901
  * lock timeout.
916
902
  */
917
903
  async gracefulShutdown() {
904
+ this._stopProviderPolling();
918
905
  const rawDrainMs = Number.parseInt(process.env.PILOTSWARM_WORKER_SHUTDOWN_TIMEOUT_MS || "", 10);
919
906
  const drainBudgetMs = Number.isFinite(rawDrainMs) && rawDrainMs >= 0 ? rawDrainMs : 60_000;
920
907
  // Advertise draining before the runtime drain so operators see the
@@ -1014,9 +1001,9 @@ export class PilotSwarmWorker {
1014
1001
  * a broken package degrades to "packages unchanged/quarantined", never
1015
1002
  * to a dead worker.
1016
1003
  *
1017
- * Hot-swap semantics (existing runtime behavior, relied on, not added):
1018
- * prompts re-read per turn, tool HANDLERS re-register per turn, tool
1019
- * DECLARATIONS and MCP configs reach the CLI only on cold create/resume.
1004
+ * SessionManager adopts one package snapshot per turn. Handler-only changes
1005
+ * re-register in place; changed prompts, declarations or MCP grants recreate
1006
+ * the warm CLI handle at the next turn boundary.
1020
1007
  */
1021
1008
  _startConfigurationPolling() {
1022
1009
  if (!this._catalog || this._agentPackagesTimer)
@@ -1069,6 +1056,15 @@ export class PilotSwarmWorker {
1069
1056
  continue;
1070
1057
  try {
1071
1058
  const tools = await loadAgentPackageTools(pkg, { workerNodeId: this.config.workerNodeId });
1059
+ const collision = findReservedPackageToolName(tools.map((tool) => String(tool?.name || "")), [
1060
+ ...ManagedSession.systemToolDefs().map((tool) => String(tool.name)),
1061
+ ...ManagedSession.subAgentToolDefs().map((tool) => String(tool.name)),
1062
+ ...this._frameworkBaseToolNames,
1063
+ ...this._appDefaultToolNames,
1064
+ ], this.toolRegistry.keys());
1065
+ if (collision) {
1066
+ throw new Error(`package tool "${collision}" conflicts with a reserved platform or deployment tool`);
1067
+ }
1072
1068
  const ownMap = new Map();
1073
1069
  for (const tool of tools) {
1074
1070
  packageTools.set(tool.name, tool);
@@ -1319,7 +1315,7 @@ export class PilotSwarmWorker {
1319
1315
  const { mcpServers: _refs, inheritDefaultMcpServers: _inherit, ...rest } = agent;
1320
1316
  const mcpKey = agent.packageId
1321
1317
  ? packageAgentKey(agent.packageId, agent.name)
1322
- : agent.name;
1318
+ : agent.namespace ? `${agent.namespace}:${agent.name}` : agent.name;
1323
1319
  return {
1324
1320
  ...rest,
1325
1321
  // The agent's OWN prompt (skills already composed in), never
@@ -1330,8 +1326,8 @@ export class PilotSwarmWorker {
1330
1326
  appDefault: this._appDefaultPrompt,
1331
1327
  activeAgentPrompt: agent.prompt,
1332
1328
  }) ?? agent.prompt,
1333
- // mcpKey is the qualified key for a package agent, the bare
1334
- // name for a deployment/inline one — the only keys registered.
1329
+ // MCP uses the exact same copy as the authored prompt, even
1330
+ // when two static namespaces declare the same agent name.
1335
1331
  ...(this._agentMcpServers[mcpKey]
1336
1332
  ? { mcpServers: this._agentMcpServers[mcpKey] }
1337
1333
  : {}),
@@ -1477,19 +1473,11 @@ export class PilotSwarmWorker {
1477
1473
  console.warn(`[PilotSwarmWorker] Direct worker-config mcpServers (${this._directConfigMcpNames.join(", ")}) ` +
1478
1474
  `apply to every session (legacy). Prefer per-agent frontmatter declarations or tagging catalog servers "default": true.`);
1479
1475
  }
1480
- // Per-agent maps. Agents merge by name with later definitions
1481
- // overriding earlier ones (same contract as prompt resolution), so
1482
- // ALWAYS assign: a later definition with no MCP declarations must
1483
- // clear a shadowed definition's grants, never inherit them.
1484
- //
1485
- // A PACKAGE agent registers ONLY under a package-qualified key, never
1486
- // the bare name. With scope shadowing two copies share the bare name,
1487
- // and a bare-name entry is last-write-wins — a session resolving one
1488
- // copy could read the other's grants (or a user package could strip a
1489
- // deployment agent's grants fleet-wide). The bare name is therefore
1490
- // reserved for deployment/inline agents, which have no packageId; the
1491
- // session-manager reads the qualified key for package copies and the
1492
- // bare key only for non-package agents.
1476
+ // Published agents use package-qualified keys. Static definitions use
1477
+ // namespace-qualified keys; the bare alias retains the first static
1478
+ // definition, matching the prompt lookup's deployment default. Never
1479
+ // let a same-name package or another namespace replace these grants.
1480
+ const assignedStaticKeys = new Set();
1493
1481
  for (const agent of [...this._rawLoadedAgents, ...this._loadedSystemAgents]) {
1494
1482
  const resolved = {};
1495
1483
  if (agent.inheritDefaultMcpServers === true) {
@@ -1501,14 +1489,21 @@ export class PilotSwarmWorker {
1501
1489
  packageId: agent.packageId ?? null,
1502
1490
  packageScope: agent.packageScope ?? null,
1503
1491
  });
1504
- const key = agent.packageId
1505
- ? packageAgentKey(agent.packageId, agent.name)
1506
- : agent.name;
1507
- if (Object.keys(resolved).length > 0) {
1508
- this._agentMcpServers[key] = resolved;
1509
- }
1510
- else {
1511
- delete this._agentMcpServers[key];
1492
+ const packageId = agent.packageId;
1493
+ const keys = packageId
1494
+ ? [packageAgentKey(packageId, agent.name)]
1495
+ : [...new Set([agent.name, ...(agent.namespace ? [`${agent.namespace}:${agent.name}`] : [])])];
1496
+ for (const key of keys) {
1497
+ if (!packageId && assignedStaticKeys.has(key))
1498
+ continue;
1499
+ if (!packageId)
1500
+ assignedStaticKeys.add(key);
1501
+ if (Object.keys(resolved).length > 0) {
1502
+ this._agentMcpServers[key] = resolved;
1503
+ }
1504
+ else {
1505
+ delete this._agentMcpServers[key];
1506
+ }
1512
1507
  }
1513
1508
  }
1514
1509
  }
@@ -1663,6 +1658,7 @@ export class PilotSwarmWorker {
1663
1658
  const winner = [...agents].sort((a, b) => rank(a) - rank(b))[0];
1664
1659
  const copyOf = (agent) => ({
1665
1660
  prompt: agent.prompt,
1661
+ toolNames: [...(agent.tools ?? [])],
1666
1662
  kind: agent.promptLayerKind ?? "app-agent",
1667
1663
  descriptor: agent.layerDescriptor,
1668
1664
  ...(agent.packageId ? {
@@ -1675,6 +1671,19 @@ export class PilotSwarmWorker {
1675
1671
  ...copyOf(winner),
1676
1672
  ...(agents.length > 1 ? { copies: agents.map(copyOf) } : {}),
1677
1673
  };
1674
+ // Persisted static bindings use this exact namespace key. The
1675
+ // alias carries the composed prompt, declarations and descriptor
1676
+ // of that copy, never the bare-name winner from another namespace.
1677
+ const assignedAliases = new Set();
1678
+ for (const agent of agents) {
1679
+ if (agent.packageId || !agent.namespace)
1680
+ continue;
1681
+ const key = `${agent.namespace}:${agent.name}`;
1682
+ if (assignedAliases.has(key))
1683
+ continue;
1684
+ assignedAliases.add(key);
1685
+ this._agentPromptLookup[key] = copyOf(agent);
1686
+ }
1678
1687
  if (agents.length > 1) {
1679
1688
  console.warn(`[PilotSwarmWorker] agent name "${name}" is served by ${agents.length} loaded copies `
1680
1689
  + `(${agents.map((a) => a.packageId ? `${a.packageScope ?? "shared"} package` : "deployment").join(", ")}); `
@@ -1916,6 +1925,8 @@ export class PilotSwarmWorker {
1916
1925
  }
1917
1926
  const overrideByAgent = new Map(overrides.map((override) => [override.agentId, override]));
1918
1927
  for (const plan of resolveSystemAgentSessionPlans(this._loadedSystemAgents)) {
1928
+ if (!this._providerReconciliationEnabled)
1929
+ return;
1919
1930
  const override = overrideByAgent.get(plan.agent.id);
1920
1931
  const route = override ?? systemDefault;
1921
1932
  if (!route.model || !this._modelProviders?.hasModel(route.model)) {