pilotswarm-sdk 0.4.0 → 0.5.0

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 (164) hide show
  1. package/api/src/http-api-transport.js +4 -4
  2. package/api/src/protocol.js +10 -3
  3. package/dist/agent-loader.d.ts +2 -0
  4. package/dist/agent-loader.d.ts.map +1 -1
  5. package/dist/agent-loader.js +7 -1
  6. package/dist/agent-loader.js.map +1 -1
  7. package/dist/blob-store.d.ts +10 -1
  8. package/dist/blob-store.d.ts.map +1 -1
  9. package/dist/blob-store.js +275 -13
  10. package/dist/blob-store.js.map +1 -1
  11. package/dist/client.d.ts +1 -0
  12. package/dist/client.d.ts.map +1 -1
  13. package/dist/client.js +5 -1
  14. package/dist/client.js.map +1 -1
  15. package/dist/cms-migrations.d.ts.map +1 -1
  16. package/dist/cms-migrations.js +544 -1
  17. package/dist/cms-migrations.js.map +1 -1
  18. package/dist/cms.d.ts +18 -4
  19. package/dist/cms.d.ts.map +1 -1
  20. package/dist/cms.js +62 -3
  21. package/dist/cms.js.map +1 -1
  22. package/dist/fault-injection.d.ts +2 -0
  23. package/dist/fault-injection.d.ts.map +1 -0
  24. package/dist/fault-injection.js +45 -0
  25. package/dist/fault-injection.js.map +1 -0
  26. package/dist/management-client.d.ts +6 -2
  27. package/dist/management-client.d.ts.map +1 -1
  28. package/dist/management-client.js +8 -4
  29. package/dist/management-client.js.map +1 -1
  30. package/dist/orchestration/index.d.ts +3 -3
  31. package/dist/orchestration/index.js +1 -1
  32. package/dist/orchestration/lifecycle.d.ts +9 -2
  33. package/dist/orchestration/lifecycle.d.ts.map +1 -1
  34. package/dist/orchestration/lifecycle.js +21 -55
  35. package/dist/orchestration/lifecycle.js.map +1 -1
  36. package/dist/orchestration/runtime.d.ts +1 -1
  37. package/dist/orchestration/state.d.ts +7 -3
  38. package/dist/orchestration/state.d.ts.map +1 -1
  39. package/dist/orchestration/state.js +13 -4
  40. package/dist/orchestration/state.js.map +1 -1
  41. package/dist/orchestration/turn.d.ts.map +1 -1
  42. package/dist/orchestration/turn.js +98 -66
  43. package/dist/orchestration/turn.js.map +1 -1
  44. package/dist/orchestration-registry.d.ts.map +1 -1
  45. package/dist/orchestration-registry.js +6 -2
  46. package/dist/orchestration-registry.js.map +1 -1
  47. package/dist/orchestration-version.d.ts +1 -1
  48. package/dist/orchestration-version.js +1 -1
  49. package/dist/orchestration.d.ts +2 -2
  50. package/dist/orchestration.js +4 -4
  51. package/dist/orchestration_1_0_46.d.ts +1 -1
  52. package/dist/orchestration_1_0_47.d.ts +1 -1
  53. package/dist/orchestration_1_0_48.d.ts +1 -1
  54. package/dist/orchestration_1_0_49.d.ts +1 -1
  55. package/dist/orchestration_1_0_50.d.ts +1 -1
  56. package/dist/orchestration_1_0_56/agents.d.ts +41 -0
  57. package/dist/orchestration_1_0_56/agents.d.ts.map +1 -0
  58. package/dist/orchestration_1_0_56/agents.js +758 -0
  59. package/dist/orchestration_1_0_56/agents.js.map +1 -0
  60. package/dist/orchestration_1_0_56/index.d.ts +24 -0
  61. package/dist/orchestration_1_0_56/index.d.ts.map +1 -0
  62. package/dist/orchestration_1_0_56/index.js +13 -0
  63. package/dist/orchestration_1_0_56/index.js.map +1 -0
  64. package/dist/orchestration_1_0_56/lifecycle.d.ts +41 -0
  65. package/dist/orchestration_1_0_56/lifecycle.d.ts.map +1 -0
  66. package/dist/orchestration_1_0_56/lifecycle.js +580 -0
  67. package/dist/orchestration_1_0_56/lifecycle.js.map +1 -0
  68. package/dist/orchestration_1_0_56/queue.d.ts +7 -0
  69. package/dist/orchestration_1_0_56/queue.d.ts.map +1 -0
  70. package/dist/orchestration_1_0_56/queue.js +644 -0
  71. package/dist/orchestration_1_0_56/queue.js.map +1 -0
  72. package/dist/orchestration_1_0_56/runtime.d.ts +29 -0
  73. package/dist/orchestration_1_0_56/runtime.d.ts.map +1 -0
  74. package/dist/orchestration_1_0_56/runtime.js +194 -0
  75. package/dist/orchestration_1_0_56/runtime.js.map +1 -0
  76. package/dist/orchestration_1_0_56/state.d.ts +126 -0
  77. package/dist/orchestration_1_0_56/state.d.ts.map +1 -0
  78. package/dist/orchestration_1_0_56/state.js +106 -0
  79. package/dist/orchestration_1_0_56/state.js.map +1 -0
  80. package/dist/orchestration_1_0_56/turn.d.ts +30 -0
  81. package/dist/orchestration_1_0_56/turn.d.ts.map +1 -0
  82. package/dist/orchestration_1_0_56/turn.js +1075 -0
  83. package/dist/orchestration_1_0_56/turn.js.map +1 -0
  84. package/dist/orchestration_1_0_56/utils.d.ts +22 -0
  85. package/dist/orchestration_1_0_56/utils.d.ts.map +1 -0
  86. package/dist/orchestration_1_0_56/utils.js +226 -0
  87. package/dist/orchestration_1_0_56/utils.js.map +1 -0
  88. package/dist/orchestration_1_0_57/agents.d.ts +41 -0
  89. package/dist/orchestration_1_0_57/agents.d.ts.map +1 -0
  90. package/dist/orchestration_1_0_57/agents.js +758 -0
  91. package/dist/orchestration_1_0_57/agents.js.map +1 -0
  92. package/dist/orchestration_1_0_57/index.d.ts +24 -0
  93. package/dist/orchestration_1_0_57/index.d.ts.map +1 -0
  94. package/dist/orchestration_1_0_57/index.js +13 -0
  95. package/dist/orchestration_1_0_57/index.js.map +1 -0
  96. package/dist/orchestration_1_0_57/lifecycle.d.ts +49 -0
  97. package/dist/orchestration_1_0_57/lifecycle.d.ts.map +1 -0
  98. package/dist/orchestration_1_0_57/lifecycle.js +583 -0
  99. package/dist/orchestration_1_0_57/lifecycle.js.map +1 -0
  100. package/dist/orchestration_1_0_57/queue.d.ts +7 -0
  101. package/dist/orchestration_1_0_57/queue.d.ts.map +1 -0
  102. package/dist/orchestration_1_0_57/queue.js +644 -0
  103. package/dist/orchestration_1_0_57/queue.js.map +1 -0
  104. package/dist/orchestration_1_0_57/runtime.d.ts +29 -0
  105. package/dist/orchestration_1_0_57/runtime.d.ts.map +1 -0
  106. package/dist/orchestration_1_0_57/runtime.js +198 -0
  107. package/dist/orchestration_1_0_57/runtime.js.map +1 -0
  108. package/dist/orchestration_1_0_57/state.d.ts +133 -0
  109. package/dist/orchestration_1_0_57/state.d.ts.map +1 -0
  110. package/dist/orchestration_1_0_57/state.js +115 -0
  111. package/dist/orchestration_1_0_57/state.js.map +1 -0
  112. package/dist/orchestration_1_0_57/turn.d.ts +30 -0
  113. package/dist/orchestration_1_0_57/turn.d.ts.map +1 -0
  114. package/dist/orchestration_1_0_57/turn.js +1110 -0
  115. package/dist/orchestration_1_0_57/turn.js.map +1 -0
  116. package/dist/orchestration_1_0_57/utils.d.ts +22 -0
  117. package/dist/orchestration_1_0_57/utils.d.ts.map +1 -0
  118. package/dist/orchestration_1_0_57/utils.js +226 -0
  119. package/dist/orchestration_1_0_57/utils.js.map +1 -0
  120. package/dist/session-lifecycle.d.ts +80 -0
  121. package/dist/session-lifecycle.d.ts.map +1 -0
  122. package/dist/session-lifecycle.js +257 -0
  123. package/dist/session-lifecycle.js.map +1 -0
  124. package/dist/session-manager.d.ts +21 -0
  125. package/dist/session-manager.d.ts.map +1 -1
  126. package/dist/session-manager.js +137 -1
  127. package/dist/session-manager.js.map +1 -1
  128. package/dist/session-proxy.d.ts +6 -1
  129. package/dist/session-proxy.d.ts.map +1 -1
  130. package/dist/session-proxy.js +1123 -953
  131. package/dist/session-proxy.js.map +1 -1
  132. package/dist/session-store.d.ts +48 -3
  133. package/dist/session-store.d.ts.map +1 -1
  134. package/dist/session-store.js +394 -28
  135. package/dist/session-store.js.map +1 -1
  136. package/dist/snapshot-protocol.d.ts +101 -0
  137. package/dist/snapshot-protocol.d.ts.map +1 -0
  138. package/dist/snapshot-protocol.js +120 -0
  139. package/dist/snapshot-protocol.js.map +1 -0
  140. package/dist/types.d.ts +26 -1
  141. package/dist/types.d.ts.map +1 -1
  142. package/dist/types.js.map +1 -1
  143. package/dist/wait-affinity.d.ts +11 -0
  144. package/dist/wait-affinity.d.ts.map +1 -1
  145. package/dist/wait-affinity.js +6 -0
  146. package/dist/wait-affinity.js.map +1 -1
  147. package/dist/web/web-client.d.ts +1 -0
  148. package/dist/web/web-client.d.ts.map +1 -1
  149. package/dist/web/web-client.js +1 -0
  150. package/dist/web/web-client.js.map +1 -1
  151. package/dist/web/web-management-client.d.ts +30 -11
  152. package/dist/web/web-management-client.d.ts.map +1 -1
  153. package/dist/web/web-management-client.js +34 -19
  154. package/dist/web/web-management-client.js.map +1 -1
  155. package/dist/worker.d.ts +16 -1
  156. package/dist/worker.d.ts.map +1 -1
  157. package/dist/worker.js +92 -13
  158. package/dist/worker.js.map +1 -1
  159. package/package.json +7 -4
  160. package/plugins/mgmt/agents/agent-tuner.agent.md +6 -0
  161. package/plugins/mgmt/agents/facts-manager.agent.md +6 -0
  162. package/plugins/mgmt/agents/pilotswarm.agent.md +6 -0
  163. package/plugins/mgmt/agents/resourcemgr.agent.md +6 -0
  164. package/plugins/mgmt/agents/sweeper.agent.md +6 -0
@@ -288,12 +288,12 @@ export class HttpApiTransport {
288
288
 
289
289
  // ── Events / history ────────────────────────────────────────────────
290
290
 
291
- async getSessionEvents(sessionId, afterSeq, limit) {
292
- return this.api.call("getSessionEvents", { sessionId, afterSeq, limit });
291
+ async getSessionEvents(sessionId, afterSeq, limit, eventTypes) {
292
+ return this.api.call("getSessionEvents", { sessionId, afterSeq, limit, eventTypes });
293
293
  }
294
294
 
295
- async getSessionEventsBefore(sessionId, beforeSeq, limit) {
296
- return this.api.call("getSessionEventsBefore", { sessionId, beforeSeq, limit });
295
+ async getSessionEventsBefore(sessionId, beforeSeq, limit, eventTypes) {
296
+ return this.api.call("getSessionEventsBefore", { sessionId, beforeSeq, limit, eventTypes });
297
297
  }
298
298
 
299
299
  async getExecutionHistory(sessionId, executionId) {
@@ -46,7 +46,7 @@ export const OPERATIONS = [
46
46
  // ── Sessions (client surface) ───────────────────────────────────────
47
47
  { name: "listSessions", method: "GET", path: "/sessions", summary: "List session summaries." },
48
48
  { name: "createSession", method: "POST", path: "/sessions", params: { model: body(), reasoningEffort: body(), groupId: body() }, summary: "Create a session. Owner is the authenticated principal." },
49
- { name: "createSessionForAgent", method: "POST", path: "/sessions/for-agent", params: { agentName: body(), model: body(), reasoningEffort: body(), title: body(), splash: body(), initialPrompt: body(), groupId: body() }, summary: "Create a session bound to a named agent." },
49
+ { name: "createSessionForAgent", method: "POST", path: "/sessions/for-agent", params: { agentName: body(), model: body(), reasoningEffort: body(), title: body(), splash: body(), splashMobile: body(), initialPrompt: body(), groupId: body() }, summary: "Create a session bound to a named agent." },
50
50
  { name: "getSession", method: "GET", path: "/sessions/:sessionId", params: { sessionId: path("sessionId") }, summary: "Get one session view (live orchestration status)." },
51
51
  { name: "deleteSession", method: "DELETE", path: "/sessions/:sessionId", params: { sessionId: path("sessionId") }, summary: "Cancel and soft-delete a session." },
52
52
  { name: "sendMessage", method: "POST", path: "/sessions/:sessionId/messages", params: { sessionId: path("sessionId"), prompt: body(), options: body() }, summary: "Send a prompt (options: { enqueueOnly?, clientMessageIds? })." },
@@ -75,8 +75,8 @@ export const OPERATIONS = [
75
75
  { name: "getLatestResponse", method: "GET", path: "/management/sessions/:sessionId/latest-response", params: { sessionId: path("sessionId") }, summary: "Latest turn response payload, if any." },
76
76
  { name: "getOrchestrationStats", method: "GET", path: "/management/sessions/:sessionId/orchestration-stats", params: { sessionId: path("sessionId") }, summary: "Orchestration runtime stats." },
77
77
  { name: "getExecutionHistory", method: "GET", path: "/management/sessions/:sessionId/execution-history", params: { sessionId: path("sessionId"), executionId: query("number") }, summary: "Raw execution history events." },
78
- { name: "getSessionEvents", method: "GET", path: "/management/sessions/:sessionId/events", params: { sessionId: path("sessionId"), afterSeq: query("number"), limit: query("number") }, summary: "Session events after a sequence number (reconnect catch-up)." },
79
- { name: "getSessionEventsBefore", method: "GET", path: "/management/sessions/:sessionId/events-before", params: { sessionId: path("sessionId"), beforeSeq: query("number"), limit: query("number") }, summary: "Older session events for history paging." },
78
+ { name: "getSessionEvents", method: "GET", path: "/management/sessions/:sessionId/events", params: { sessionId: path("sessionId"), afterSeq: query("number"), limit: query("number"), eventTypes: query("json") }, summary: "Session events after a sequence number (reconnect catch-up). Optional eventTypes (JSON string array) narrows to those event types server-side." },
79
+ { name: "getSessionEventsBefore", method: "GET", path: "/management/sessions/:sessionId/events-before", params: { sessionId: path("sessionId"), beforeSeq: query("number"), limit: query("number"), eventTypes: query("json") }, summary: "Older session events for history paging. Optional eventTypes (JSON string array) narrows to those event types server-side (chat transcript paging)." },
80
80
  { name: "getSessionMetricSummary", method: "GET", path: "/management/sessions/:sessionId/metric-summary", params: { sessionId: path("sessionId") }, summary: "Per-session metric summary." },
81
81
  { name: "getSessionTokensByModel", method: "GET", path: "/management/sessions/:sessionId/tokens-by-model", params: { sessionId: path("sessionId") }, summary: "Token totals grouped by model." },
82
82
  { name: "getSessionTreeStats", method: "GET", path: "/management/sessions/:sessionId/tree-stats", params: { sessionId: path("sessionId") }, summary: "Stats rolled up across the spawn tree." },
@@ -84,6 +84,12 @@ export const OPERATIONS = [
84
84
  { name: "getSessionTreeSkillUsage", method: "GET", path: "/management/sessions/:sessionId/tree-skill-usage", params: { sessionId: path("sessionId"), since: query("string") }, summary: "Skill usage across the spawn tree." },
85
85
  { name: "getSessionFactsStats", method: "GET", path: "/management/sessions/:sessionId/facts-stats", params: { sessionId: path("sessionId") }, summary: "Facts stats for one session." },
86
86
  { name: "getSessionTreeFactsStats", method: "GET", path: "/management/sessions/:sessionId/tree-facts-stats", params: { sessionId: path("sessionId") }, summary: "Facts stats across the spawn tree." },
87
+ // Retrieval / graph observability (tuner-grade diagnostics; read-only)
88
+ { name: "getSessionRetrievalUsage", method: "GET", path: "/management/sessions/:sessionId/retrieval-usage", params: { sessionId: path("sessionId"), since: query("string") }, summary: "Retrieval (facts/graph search) usage for one session." },
89
+ { name: "getSessionTreeRetrievalUsage", method: "GET", path: "/management/sessions/:sessionId/tree-retrieval-usage", params: { sessionId: path("sessionId"), since: query("string") }, summary: "Retrieval usage across the spawn tree." },
90
+ { name: "getSessionGraphNodeUsage", method: "GET", path: "/management/sessions/:sessionId/graph-node-usage", params: { sessionId: path("sessionId"), since: query("string"), limit: query("number"), nodeKeyLike: query("string"), kind: query("string") }, summary: "Graph node usage for one session." },
91
+ { name: "getSessionGraphEdgeSearchUsage", method: "GET", path: "/management/sessions/:sessionId/graph-edge-search-usage", params: { sessionId: path("sessionId"), since: query("string"), limit: query("number") }, summary: "Graph edge-search usage for one session." },
92
+ { name: "getSessionGraphSearches", method: "GET", path: "/management/sessions/:sessionId/graph-searches", params: { sessionId: path("sessionId"), limit: query("number") }, summary: "Recent graph search events for one session." },
87
93
  { name: "listChildOutcomes", method: "GET", path: "/management/sessions/:parentSessionId/child-outcomes", params: { parentSessionId: path("parentSessionId") }, summary: "Child outcomes recorded under a parent session." },
88
94
  { name: "getChildOutcome", method: "GET", path: "/management/child-outcomes/:childSessionId", params: { childSessionId: path("childSessionId") }, summary: "One child outcome." },
89
95
 
@@ -101,6 +107,7 @@ export const OPERATIONS = [
101
107
  { name: "getFleetStats", method: "GET", path: "/management/fleet/stats", params: { since: query("string"), includeDeleted: query("boolean") }, summary: "Fleet-wide stats." },
102
108
  { name: "getFleetSkillUsage", method: "GET", path: "/management/fleet/skill-usage", params: { since: query("string"), includeDeleted: query("boolean") }, summary: "Fleet-wide skill usage." },
103
109
  { name: "getFleetRetrievalUsage", method: "GET", path: "/management/fleet/retrieval-usage", params: { since: query("string"), includeDeleted: query("boolean") }, summary: "Fleet-wide retrieval usage." },
110
+ { name: "getFleetGraphNodeUsage", method: "GET", path: "/management/fleet/graph-node-usage", params: { since: query("string"), includeDeleted: query("boolean"), limit: query("number"), nodeKeyLike: query("string"), kind: query("string") }, summary: "Fleet-wide graph node usage." },
104
111
  { name: "getUserStats", method: "GET", path: "/management/users/stats", params: { since: query("string"), includeDeleted: query("boolean") }, summary: "Per-user stats." },
105
112
  { name: "getSharedFactsStats", method: "GET", path: "/management/facts/shared-stats", summary: "Shared facts stats." },
106
113
  { name: "getFactsTombstoneStats", method: "GET", path: "/management/facts/tombstone-stats", params: { ttlSeconds: query("number") }, summary: "Soft-deleted facts awaiting reconciliation." },
@@ -44,6 +44,8 @@ export interface AgentConfig {
44
44
  parent?: string;
45
45
  /** Splash banner (terminal markup) shown in the TUI when the session is selected. */
46
46
  splash?: string;
47
+ /** Narrow-viewport splash variant, swapped in when the main splash art is wider than the pane (mobile portal, narrow terminals). */
48
+ splashMobile?: string;
47
49
  /** Initial prompt to send when the system agent is first created. */
48
50
  initialPrompt?: string;
49
51
  /** Source plugin namespace (e.g. "pilotswarm", "smelter"). Set by the worker during plugin loading. */
@@ -1 +1 @@
1
- {"version":3,"file":"agent-loader.d.ts","sourceRoot":"","sources":["../src/agent-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAQH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYpD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAclF;AAID,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACxB,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qGAAqG;IACrG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qHAAqH;IACrH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uGAAuG;IACvG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,WAAW,GAAG,kBAAkB,GAAG,yBAAyB,CAAC;IAC/E;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAsHD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,EAAE,CAgE/D"}
1
+ {"version":3,"file":"agent-loader.d.ts","sourceRoot":"","sources":["../src/agent-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAQH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYpD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAclF;AAID,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACxB,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qGAAqG;IACrG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qHAAqH;IACrH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oIAAoI;IACpI,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uGAAuG;IACvG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,WAAW,GAAG,kBAAkB,GAAG,yBAAyB,CAAC;IAC/E;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAyHD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,EAAE,CAiE/D"}
@@ -83,6 +83,8 @@ function parseAgentFrontmatter(content) {
83
83
  const val = multilineValue.join("\n").trimEnd();
84
84
  if (currentKey === "splash")
85
85
  meta.splash = val;
86
+ else if (currentKey === "splashMobile")
87
+ meta.splashMobile = val;
86
88
  else if (currentKey === "initialPrompt") {
87
89
  // For > (folded) scalars, collapse newlines to spaces
88
90
  meta.initialPrompt = currentBlockStyle === ">" ? val.replace(/\n/g, " ").trim() : val;
@@ -156,7 +158,7 @@ function parseAgentFrontmatter(content) {
156
158
  // Will be followed by list items
157
159
  meta.tools = [];
158
160
  }
159
- else if ((key === "splash" || key === "initialPrompt") && (value === "|" || value === ">")) {
161
+ else if ((key === "splash" || key === "splashMobile" || key === "initialPrompt") && (value === "|" || value === ">")) {
160
162
  // YAML block scalar (| literal, > folded)
161
163
  currentBlockStyle = value;
162
164
  multilineValue = [];
@@ -164,6 +166,9 @@ function parseAgentFrontmatter(content) {
164
166
  else if (key === "splash") {
165
167
  meta.splash = value;
166
168
  }
169
+ else if (key === "splashMobile") {
170
+ meta.splashMobile = value;
171
+ }
167
172
  else if (key === "initialPrompt") {
168
173
  meta.initialPrompt = value;
169
174
  }
@@ -216,6 +221,7 @@ export function loadAgentFiles(agentsDir) {
216
221
  title: meta.title,
217
222
  parent: meta.parent,
218
223
  splash: meta.splash,
224
+ splashMobile: meta.splashMobile,
219
225
  initialPrompt: meta.initialPrompt,
220
226
  crawler,
221
227
  harvester: crawler,
@@ -1 +1 @@
1
- {"version":3,"file":"agent-loader.js","sourceRoot":"","sources":["../src/agent-loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-loader.js","sourceRoot":"","sources":["../src/agent-loader.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,7 @@
27
27
  * unmigrated stamps stay on the legacy path.
28
28
  */
29
29
  import { ContainerClient, StorageSharedKeyCredential } from "@azure/storage-blob";
30
+ import { type SnapshotCommitInput, type SnapshotCommitResult, type SnapshotHydrateResult, type SnapshotProbe, type VersionedSnapshotStore } from "./snapshot-protocol.js";
30
31
  import { type ArtifactDownloadResult, type ArtifactMetadata, type SessionStateStore, type ArtifactStore, type ArtifactUploadOptions } from "./session-store.js";
31
32
  /**
32
33
  * Configuration for constructing a {@link SessionBlobStore} against an
@@ -70,7 +71,7 @@ export interface SessionBlobStoreClientConfig {
70
71
  *
71
72
  * @internal
72
73
  */
73
- export declare class SessionBlobStore implements SessionStateStore, ArtifactStore {
74
+ export declare class SessionBlobStore implements SessionStateStore, ArtifactStore, VersionedSnapshotStore {
74
75
  private containerClient;
75
76
  private containerName;
76
77
  private credential;
@@ -97,6 +98,14 @@ export declare class SessionBlobStore implements SessionStateStore, ArtifactStor
97
98
  exists(sessionId: string): Promise<boolean>;
98
99
  /** Delete a dehydrated session from blob storage. */
99
100
  delete(sessionId: string): Promise<void>;
101
+ private static readonly COMMIT_MAX_ATTEMPTS;
102
+ private static readonly SINGLE_SHOT_MAX_BYTES;
103
+ private snapshotBlobName;
104
+ private probeFromMetadata;
105
+ private headSnapshot;
106
+ probeSnapshot(sessionId: string): Promise<SnapshotProbe>;
107
+ commitSnapshot(sessionId: string, input: SnapshotCommitInput): Promise<SnapshotCommitResult>;
108
+ hydrateSnapshot(sessionId: string): Promise<SnapshotHydrateResult>;
100
109
  private artifactBlobPath;
101
110
  /**
102
111
  * Upload an artifact file (e.g. .md) to blob storage.
@@ -1 +1 @@
1
- {"version":3,"file":"blob-store.d.ts","sourceRoot":"","sources":["../src/blob-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blob-store.d.ts","sourceRoot":"","sources":["../src/blob-store.ts"],"names":[],"mappings":"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"}
@@ -28,10 +28,13 @@
28
28
  */
29
29
  import { BlobServiceClient, StorageSharedKeyCredential, generateBlobSASQueryParameters, BlobSASPermissions, SASProtocol, } from "@azure/storage-blob";
30
30
  import { DefaultAzureCredential } from "@azure/identity";
31
+ import crypto from "node:crypto";
31
32
  import fs from "node:fs";
32
33
  import os from "node:os";
33
34
  import path from "node:path";
34
- import { DEFAULT_SESSION_STATE_DIR, archiveSessionDir, buildMetadata, extractSessionArchive, isBinaryArtifactContentType, normalizeArtifactContentType, resolveArtifactUpload, waitForSessionSnapshot, } from "./session-store.js";
35
+ import { faultPoint } from "./fault-injection.js";
36
+ import { SnapshotConflictError, } from "./snapshot-protocol.js";
37
+ import { DEFAULT_SESSION_STATE_DIR, DEFAULT_SNAPSHOT_CODEC, archiveSessionDir, buildMetadata, extractSessionArchive, isBinaryArtifactContentType, normalizeArtifactContentType, resolveArtifactUpload, resolveSnapshotCodec, waitForSessionSnapshot, } from "./session-store.js";
35
38
  function formatBlobLogValue(value) {
36
39
  if (value == null)
37
40
  return "";
@@ -130,6 +133,27 @@ export class SessionBlobStore {
130
133
  dir: sessionDir,
131
134
  reason: meta?.reason,
132
135
  });
136
+ // Versioned-snapshot fence: the committed chain (lifecycle protocol)
137
+ // already holds this session's durable state, and an unconditional
138
+ // legacy Put would replace both content and the CAS metadata
139
+ // (psver/psturnkey/pssha). Degrade to release: free local files.
140
+ try {
141
+ const head = await this.headSnapshot(sessionId);
142
+ if (head.exists && !head.legacy) {
143
+ logBlobStore("warn", sessionId, "dehydrate skipped upload: versioned snapshot exists; releasing local files only", {
144
+ container: this.containerName,
145
+ version: head.version,
146
+ });
147
+ fs.rmSync(sessionDir, { recursive: true, force: true });
148
+ return;
149
+ }
150
+ }
151
+ catch (probeErr) {
152
+ logBlobStore("warn", sessionId, "dehydrate version probe failed; proceeding with legacy upload", {
153
+ container: this.containerName,
154
+ error: errorMessage(probeErr),
155
+ });
156
+ }
133
157
  const snapshot = await waitForSessionSnapshot(this.sessionStateDir, sessionId);
134
158
  if (!snapshot.ready) {
135
159
  logBlobStore("warn", sessionId, "dehydrate snapshot not ready", {
@@ -139,20 +163,24 @@ export class SessionBlobStore {
139
163
  throw new Error(`Session state directory not ready during dehydrate: ${sessionId} (${sessionDir}). ` +
140
164
  `Missing: ${snapshot.missing.join(", ") || "unknown"}`);
141
165
  }
142
- const tarPath = path.join(os.tmpdir(), `${sessionId}.tar.gz`);
166
+ const codec = DEFAULT_SNAPSHOT_CODEC;
167
+ const tarPath = path.join(os.tmpdir(), `${sessionId}.tar`);
143
168
  try {
144
- archiveSessionDir(this.sessionStateDir, sessionId, tarPath);
169
+ const { rawSizeBytes } = await archiveSessionDir(this.sessionStateDir, sessionId, tarPath, codec);
145
170
  const tarSizeBytes = fs.existsSync(tarPath) ? fs.statSync(tarPath).size : undefined;
146
- // Upload tar
171
+ // Upload tar. The `pscodec` metadata on the tar blob is what the
172
+ // read path decodes by — brotli has no magic bytes, so an
173
+ // unversioned legacy blob without it is assumed gzip.
147
174
  const tarBlob = this.containerClient.getBlockBlobClient(`${sessionId}.tar.gz`);
148
175
  logBlobStore("info", sessionId, "dehydrate upload tar", {
149
176
  container: this.containerName,
150
177
  blob: `${sessionId}.tar.gz`,
151
178
  tarSizeBytes,
179
+ codec,
152
180
  });
153
- await tarBlob.uploadFile(tarPath);
181
+ await tarBlob.uploadFile(tarPath, { metadata: { pscodec: codec, psraw: String(rawSizeBytes) } });
154
182
  // Upload metadata
155
- const metadata = buildMetadata(tarPath, sessionId, meta);
183
+ const metadata = buildMetadata(tarPath, sessionId, { ...meta, codec, rawSizeBytes });
156
184
  this.snapshotSizeBySession.set(sessionId, metadata.sizeBytes);
157
185
  const metaBlob = this.containerClient.getBlockBlobClient(`${sessionId}.meta.json`);
158
186
  const metaJson = JSON.stringify(metadata);
@@ -199,14 +227,15 @@ export class SessionBlobStore {
199
227
  fs.rmSync(sessionDir, { recursive: true, force: true });
200
228
  }
201
229
  const tarBlob = this.containerClient.getBlockBlobClient(`${sessionId}.tar.gz`);
202
- const tarPath = path.join(os.tmpdir(), `${sessionId}.tar.gz`);
230
+ const tarPath = path.join(os.tmpdir(), `${sessionId}.tar`);
203
231
  try {
204
232
  logBlobStore("info", sessionId, "hydrate download tar", {
205
233
  container: this.containerName,
206
234
  blob: `${sessionId}.tar.gz`,
207
235
  });
208
- await tarBlob.downloadToFile(tarPath);
209
- extractSessionArchive(this.sessionStateDir, tarPath);
236
+ const response = await tarBlob.downloadToFile(tarPath);
237
+ const codec = resolveSnapshotCodec(response.metadata?.pscodec);
238
+ await extractSessionArchive(this.sessionStateDir, tarPath, codec);
210
239
  logBlobStore("info", sessionId, "hydrate complete", {
211
240
  container: this.containerName,
212
241
  restoredDir: sessionDir,
@@ -240,18 +269,37 @@ export class SessionBlobStore {
240
269
  });
241
270
  return;
242
271
  }
243
- const tarPath = path.join(os.tmpdir(), `${sessionId}.tar.gz`);
272
+ // Versioned-snapshot fence (see dehydrate): never clobber the
273
+ // CAS-protected chain with an unversioned legacy write.
274
+ try {
275
+ const head = await this.headSnapshot(sessionId);
276
+ if (head.exists && !head.legacy) {
277
+ logBlobStore("warn", sessionId, "checkpoint skipped: versioned snapshot exists", {
278
+ container: this.containerName,
279
+ version: head.version,
280
+ });
281
+ return;
282
+ }
283
+ }
284
+ catch (probeErr) {
285
+ logBlobStore("warn", sessionId, "checkpoint version probe failed; proceeding with legacy upload", {
286
+ container: this.containerName,
287
+ error: errorMessage(probeErr),
288
+ });
289
+ }
290
+ const codec = DEFAULT_SNAPSHOT_CODEC;
291
+ const tarPath = path.join(os.tmpdir(), `${sessionId}.tar`);
244
292
  try {
245
293
  logBlobStore("info", sessionId, "checkpoint start", {
246
294
  container: this.containerName,
247
295
  dir: sessionDir,
248
296
  });
249
- archiveSessionDir(this.sessionStateDir, sessionId, tarPath);
297
+ const { rawSizeBytes } = await archiveSessionDir(this.sessionStateDir, sessionId, tarPath, codec);
250
298
  const tarSizeBytes = fs.existsSync(tarPath) ? fs.statSync(tarPath).size : undefined;
251
299
  const tarBlob = this.containerClient.getBlockBlobClient(`${sessionId}.tar.gz`);
252
- await tarBlob.uploadFile(tarPath);
300
+ await tarBlob.uploadFile(tarPath, { metadata: { pscodec: codec, psraw: String(rawSizeBytes) } });
253
301
  // Update metadata to reflect checkpoint (not full dehydration)
254
- const metadata = buildMetadata(tarPath, sessionId, { reason: "checkpoint" });
302
+ const metadata = buildMetadata(tarPath, sessionId, { reason: "checkpoint", codec, rawSizeBytes });
255
303
  this.snapshotSizeBySession.set(sessionId, metadata.sizeBytes);
256
304
  const metaBlob = this.containerClient.getBlockBlobClient(`${sessionId}.meta.json`);
257
305
  const metaJson = JSON.stringify(metadata);
@@ -347,6 +395,220 @@ export class SessionBlobStore {
347
395
  throw error;
348
396
  }
349
397
  }
398
+ // ─── Versioned CAS contract (session-lifecycle-protocol §3.1) ───
399
+ //
400
+ // The version is an explicit counter in the tar blob's metadata
401
+ // (`psver`, plus `psturnkey` + `pssha`), written atomically with the
402
+ // content by single-shot Put Blob. The ETag is never the version — it is
403
+ // the atomicity token binding each HEAD to the conditional PUT that
404
+ // follows it (`If-Match`). A blob without `psver` is a legacy snapshot
405
+ // (probe reports version 0 / legacy). Two footguns, per the store
406
+ // proposal: never staged Put Block uploads (the condition only applies
407
+ // at commit and concurrent stagers interleave), and never Set Blob
408
+ // Metadata for version bumps (it would decouple counter from content).
409
+ static COMMIT_MAX_ATTEMPTS = 5;
410
+ static SINGLE_SHOT_MAX_BYTES = 256 * 1024 * 1024;
411
+ snapshotBlobName(sessionId) {
412
+ return `${sessionId}.tar.gz`;
413
+ }
414
+ probeFromMetadata(metadata, etag) {
415
+ const codec = resolveSnapshotCodec(metadata?.pscodec);
416
+ const raw = Number(metadata?.psraw);
417
+ const version = Number(metadata?.psver);
418
+ if (!Number.isFinite(version) || version < 1) {
419
+ return { exists: true, version: 0, legacy: true, codec, ...(etag ? { etag } : {}) };
420
+ }
421
+ return {
422
+ exists: true,
423
+ version,
424
+ ...(metadata?.psturnkey ? { turnKey: metadata.psturnkey } : {}),
425
+ ...(metadata?.pssha ? { contentHash: metadata.pssha } : {}),
426
+ ...(Number.isFinite(raw) ? { rawSizeBytes: raw } : {}),
427
+ codec,
428
+ ...(etag ? { etag } : {}),
429
+ };
430
+ }
431
+ async headSnapshot(sessionId) {
432
+ const blob = this.containerClient.getBlockBlobClient(this.snapshotBlobName(sessionId));
433
+ try {
434
+ const props = await blob.getProperties();
435
+ return this.probeFromMetadata(props.metadata, props.etag);
436
+ }
437
+ catch (error) {
438
+ if (error?.statusCode === 404)
439
+ return { exists: false, version: 0 };
440
+ throw error;
441
+ }
442
+ }
443
+ async probeSnapshot(sessionId) {
444
+ const { etag: _etag, ...probe } = await this.headSnapshot(sessionId);
445
+ return probe;
446
+ }
447
+ async commitSnapshot(sessionId, input) {
448
+ const sessionDir = path.join(this.sessionStateDir, sessionId);
449
+ const snapshot = await waitForSessionSnapshot(this.sessionStateDir, sessionId);
450
+ if (!snapshot.ready) {
451
+ throw new Error(`Session state directory not ready during commit: ${sessionId} (${sessionDir}). ` +
452
+ `Missing: ${snapshot.missing.join(", ") || "unknown"}`);
453
+ }
454
+ const codec = DEFAULT_SNAPSHOT_CODEC;
455
+ const tarPath = path.join(os.tmpdir(), `ps-commit-${sessionId}-${process.pid}-${Date.now()}.tar`);
456
+ try {
457
+ const { rawSizeBytes } = await archiveSessionDir(this.sessionStateDir, sessionId, tarPath, codec);
458
+ const body = fs.readFileSync(tarPath);
459
+ if (body.length > SessionBlobStore.SINGLE_SHOT_MAX_BYTES) {
460
+ throw new Error(`Session snapshot for ${sessionId} is ${body.length} bytes — over the ` +
461
+ `${SessionBlobStore.SINGLE_SHOT_MAX_BYTES} single-shot commit cap. ` +
462
+ `Audit the session workspace for files that belong in tar excludes.`);
463
+ }
464
+ const contentHash = crypto.createHash("sha256").update(body).digest("hex");
465
+ const blob = this.containerClient.getBlockBlobClient(this.snapshotBlobName(sessionId));
466
+ for (let attempt = 1; attempt <= SessionBlobStore.COMMIT_MAX_ATTEMPTS; attempt++) {
467
+ const head = await this.headSnapshot(sessionId);
468
+ if (head.exists && head.version === input.baseVersion + 1 && head.turnKey === input.turnKey) {
469
+ logBlobStore("info", sessionId, "commit already landed (idempotent retry)", {
470
+ version: head.version,
471
+ turnKey: input.turnKey,
472
+ });
473
+ return {
474
+ version: head.version,
475
+ contentHash: head.contentHash ?? "",
476
+ ...(head.rawSizeBytes != null ? { rawSizeBytes: head.rawSizeBytes } : {}),
477
+ alreadyCommitted: true,
478
+ };
479
+ }
480
+ if (head.exists && head.version !== input.baseVersion) {
481
+ throw new SnapshotConflictError(sessionId, input.baseVersion, head.version, head.turnKey);
482
+ }
483
+ // head.exists && version === baseVersion (legacy counts as 0),
484
+ // or !exists (any baseVersion commits as a fresh chain — the
485
+ // store lost data and the worker's copy is the only truth).
486
+ const version = head.exists ? head.version + 1 : input.baseVersion + 1;
487
+ const conditions = head.exists && head.etag
488
+ ? { ifMatch: head.etag }
489
+ : { ifNoneMatch: "*" };
490
+ faultPoint("store.commit.before-write");
491
+ try {
492
+ await blob.upload(body, body.length, {
493
+ conditions,
494
+ metadata: {
495
+ psver: String(version),
496
+ psturnkey: input.turnKey,
497
+ pssha: contentHash,
498
+ pscodec: codec,
499
+ psraw: String(rawSizeBytes),
500
+ },
501
+ });
502
+ faultPoint("store.commit.after-write");
503
+ // Legacy compat: keep <sessionId>.meta.json fresh so
504
+ // getSnapshotSizeBytes and older tooling keep working.
505
+ // Unconditional + best-effort — it is informational only.
506
+ try {
507
+ const metadata = {
508
+ ...buildMetadata(tarPath, sessionId, { reason: "turn-commit" }),
509
+ version,
510
+ turnKey: input.turnKey,
511
+ contentHash,
512
+ codec,
513
+ rawSizeBytes,
514
+ };
515
+ this.snapshotSizeBySession.set(sessionId, metadata.sizeBytes);
516
+ const metaBlob = this.containerClient.getBlockBlobClient(`${sessionId}.meta.json`);
517
+ const metaJson = JSON.stringify(metadata);
518
+ await metaBlob.upload(metaJson, metaJson.length);
519
+ }
520
+ catch (metaErr) {
521
+ logBlobStore("warn", sessionId, "commit meta.json refresh failed (non-fatal)", {
522
+ error: errorMessage(metaErr),
523
+ });
524
+ }
525
+ logBlobStore("info", sessionId, "commit complete", {
526
+ version,
527
+ turnKey: input.turnKey,
528
+ tarSizeBytes: body.length,
529
+ rawSizeBytes,
530
+ codec,
531
+ attempt,
532
+ });
533
+ return { version, contentHash, sizeBytes: body.length, rawSizeBytes, alreadyCommitted: false };
534
+ }
535
+ catch (error) {
536
+ // 412 Precondition Failed (If-Match lost the race) or
537
+ // 409 BlobAlreadyExists (If-None-Match create race):
538
+ // re-HEAD and re-evaluate — the winner may have been our
539
+ // own prior attempt (idempotent success) or a foreign
540
+ // writer (conflict), both handled at the top of the loop.
541
+ const status = error?.statusCode;
542
+ if (status === 412 || status === 409) {
543
+ logBlobStore("warn", sessionId, "commit CAS race, re-evaluating", {
544
+ attempt,
545
+ status,
546
+ });
547
+ continue;
548
+ }
549
+ throw error;
550
+ }
551
+ }
552
+ throw new Error(`Snapshot commit for ${sessionId} exhausted CAS retries`);
553
+ }
554
+ finally {
555
+ try {
556
+ fs.unlinkSync(tarPath);
557
+ }
558
+ catch { }
559
+ }
560
+ }
561
+ async hydrateSnapshot(sessionId) {
562
+ const sessionDir = path.join(this.sessionStateDir, sessionId);
563
+ const blob = this.containerClient.getBlockBlobClient(this.snapshotBlobName(sessionId));
564
+ const tarPath = path.join(os.tmpdir(), `ps-hydrate-${sessionId}-${process.pid}-${Date.now()}.tar`);
565
+ // One download response carries body + metadata consistently.
566
+ let metadata;
567
+ let tarSizeBytes;
568
+ try {
569
+ const response = await blob.downloadToFile(tarPath, 0);
570
+ metadata = response.metadata;
571
+ try {
572
+ tarSizeBytes = fs.statSync(tarPath).size;
573
+ }
574
+ catch { }
575
+ const codec = resolveSnapshotCodec(metadata?.pscodec);
576
+ fs.mkdirSync(this.sessionStateDir, { recursive: true });
577
+ const tempRoot = fs.mkdtempSync(path.join(this.sessionStateDir, `.ps-hydrate-${sessionId}-`));
578
+ try {
579
+ await extractSessionArchive(tempRoot, tarPath, codec);
580
+ const extracted = path.join(tempRoot, sessionId);
581
+ if (!fs.existsSync(extracted)) {
582
+ throw new Error(`Snapshot archive for ${sessionId} did not contain the session directory`);
583
+ }
584
+ faultPoint("store.hydrate.before-swap");
585
+ fs.rmSync(sessionDir, { recursive: true, force: true });
586
+ fs.renameSync(extracted, sessionDir);
587
+ }
588
+ finally {
589
+ fs.rmSync(tempRoot, { recursive: true, force: true });
590
+ }
591
+ }
592
+ finally {
593
+ try {
594
+ fs.unlinkSync(tarPath);
595
+ }
596
+ catch { }
597
+ }
598
+ const probe = this.probeFromMetadata(metadata, undefined);
599
+ logBlobStore("info", sessionId, "versioned hydrate complete", {
600
+ version: probe.version,
601
+ legacy: probe.legacy,
602
+ });
603
+ return {
604
+ version: probe.version,
605
+ ...(probe.turnKey ? { turnKey: probe.turnKey } : {}),
606
+ ...(probe.contentHash ? { contentHash: probe.contentHash } : {}),
607
+ ...(tarSizeBytes != null ? { sizeBytes: tarSizeBytes } : {}),
608
+ ...(probe.rawSizeBytes != null ? { rawSizeBytes: probe.rawSizeBytes } : {}),
609
+ ...(probe.legacy ? { legacy: true } : {}),
610
+ };
611
+ }
350
612
  // ─── Artifact Storage ────────────────────────────────────
351
613
  artifactBlobPath(sessionId, filename) {
352
614
  // Sanitize filename — strip path separators