super-dsh 0.1.6 → 0.1.10

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 (248) hide show
  1. package/README.md +25 -3
  2. package/agent-agy/cordis.patch.yml +7 -4
  3. package/agent-agy/dist/agent.d.ts +12 -11
  4. package/agent-agy/dist/agy-auth-gateway.d.ts +124 -0
  5. package/agent-agy/dist/agy-auth-gateway.js +233 -0
  6. package/agent-agy/dist/agy-auth.d.ts +153 -0
  7. package/agent-agy/dist/agy-auth.js +179 -0
  8. package/agent-agy/dist/agy-cli-client.d.ts +39 -9
  9. package/agent-agy/dist/agy-cli-client.js +82 -18
  10. package/agent-agy/dist/agy-store.d.ts +8 -0
  11. package/agent-agy/dist/index.d.ts +46 -16
  12. package/agent-agy/dist/index.js +82 -56
  13. package/agent-agy/dist/models.d.ts +70 -0
  14. package/agent-agy/dist/models.js +102 -3
  15. package/agent-agy/package.json +7 -5
  16. package/agent-agy-sdk/cordis.patch.yml +58 -0
  17. package/agent-agy-sdk/dist/adapter.d.ts +15 -0
  18. package/agent-agy-sdk/dist/adapter.js +42 -0
  19. package/agent-agy-sdk/dist/agent-preset-agy.d.ts +27 -0
  20. package/agent-agy-sdk/dist/agent-preset-agy.js +32 -0
  21. package/agent-agy-sdk/dist/agent.d.ts +138 -0
  22. package/agent-agy-sdk/dist/agent.js +494 -0
  23. package/{agent-agy → agent-agy-sdk}/dist/agy-client.d.ts +26 -6
  24. package/{agent-agy → agent-agy-sdk}/dist/agy-client.js +43 -25
  25. package/agent-agy-sdk/dist/agy-sessions.d.ts +25 -0
  26. package/agent-agy-sdk/dist/agy-sessions.js +107 -0
  27. package/agent-agy-sdk/dist/agy-store.d.ts +39 -0
  28. package/agent-agy-sdk/dist/agy-store.js +83 -0
  29. package/agent-agy-sdk/dist/inbox.d.ts +26 -0
  30. package/agent-agy-sdk/dist/inbox.js +53 -0
  31. package/agent-agy-sdk/dist/index.d.ts +93 -0
  32. package/agent-agy-sdk/dist/index.js +476 -0
  33. package/agent-agy-sdk/dist/models.d.ts +41 -0
  34. package/agent-agy-sdk/dist/models.js +74 -0
  35. package/agent-agy-sdk/dist/sdk-venv.d.ts +76 -0
  36. package/agent-agy-sdk/dist/sdk-venv.js +173 -0
  37. package/agent-agy-sdk/dist/world-plugin.d.ts +10 -0
  38. package/agent-agy-sdk/dist/world-plugin.js +82 -0
  39. package/agent-agy-sdk/package.json +64 -0
  40. package/agent-codex/README.md +141 -36
  41. package/agent-codex/cordis.patch.yml +14 -10
  42. package/agent-codex/dist/adapter.js +64 -28
  43. package/agent-codex/dist/agent.js +255 -81
  44. package/agent-codex/dist/app-server-approvals.js +165 -0
  45. package/agent-codex/dist/app-server-client.js +723 -0
  46. package/agent-codex/dist/app-server-events.js +432 -0
  47. package/agent-codex/dist/app-server-protocol.js +95 -0
  48. package/agent-codex/dist/app-server-wire.js +299 -0
  49. package/agent-codex/dist/codex-launch.js +78 -0
  50. package/agent-codex/dist/codex-native-config.js +392 -0
  51. package/agent-codex/dist/codex-provider-gateway.js +402 -0
  52. package/agent-codex/dist/codex-providers.js +376 -0
  53. package/agent-codex/dist/codex-route.js +86 -0
  54. package/agent-codex/dist/index.js +256 -115
  55. package/agent-codex/dist/permission.js +75 -1
  56. package/agent-codex/package.json +1 -2
  57. package/agent-codex-sdk/README.md +79 -0
  58. package/agent-codex-sdk/cordis.patch.yml +81 -0
  59. package/agent-codex-sdk/dist/adapter.js +91 -0
  60. package/agent-codex-sdk/dist/agent-preset-codex.js +32 -0
  61. package/agent-codex-sdk/dist/agent.js +1085 -0
  62. package/agent-codex-sdk/dist/codex-native-config.js +392 -0
  63. package/agent-codex-sdk/dist/codex-provider-gateway.js +402 -0
  64. package/agent-codex-sdk/dist/codex-providers.js +376 -0
  65. package/agent-codex-sdk/dist/codex-route.js +86 -0
  66. package/{agent-codex/dist/codex-client.js → agent-codex-sdk/dist/codex-sdk-client.js} +253 -32
  67. package/agent-codex-sdk/dist/codex-sdk-launch.js +92 -0
  68. package/agent-codex-sdk/dist/codex-store.js +180 -0
  69. package/agent-codex-sdk/dist/inbox.js +53 -0
  70. package/agent-codex-sdk/dist/index.js +739 -0
  71. package/agent-codex-sdk/dist/permission.js +71 -0
  72. package/agent-codex-sdk/dist/sdk-runtime.js +307 -0
  73. package/agent-codex-sdk/dist/session-map.js +167 -0
  74. package/agent-codex-sdk/dist/world-plugin.js +93 -0
  75. package/agent-codex-sdk/package.json +79 -0
  76. package/agent-codex-sdk/scripts/fetch-sdk-runtime.mjs +57 -0
  77. package/agent-omp/README.md +72 -55
  78. package/agent-omp/dist/agent.js +36 -11
  79. package/agent-omp/dist/index.js +92 -52
  80. package/agent-omp/dist/lazy-rpc.js +11 -4
  81. package/agent-omp/dist/omp-cli.js +114 -97
  82. package/agent-omp/dist/omp-store.js +12 -4
  83. package/agent-omp/dist/permission.js +70 -5
  84. package/agent-omp/dist/rpc-client.js +409 -0
  85. package/agent-omp/dist/world-plugin.js +36 -3
  86. package/agent-omp/package.json +2 -6
  87. package/agent-omp-sdk/README.md +103 -0
  88. package/agent-omp-sdk/cordis.patch.yml +108 -0
  89. package/agent-omp-sdk/dist/adapter.d.ts +21 -0
  90. package/agent-omp-sdk/dist/adapter.js +36 -0
  91. package/agent-omp-sdk/dist/agent-preset-omp.d.ts +31 -0
  92. package/agent-omp-sdk/dist/agent-preset-omp.js +32 -0
  93. package/agent-omp-sdk/dist/agent.d.ts +64 -0
  94. package/agent-omp-sdk/dist/agent.js +1178 -0
  95. package/agent-omp-sdk/dist/discovery.d.ts +57 -0
  96. package/agent-omp-sdk/dist/discovery.js +116 -0
  97. package/agent-omp-sdk/dist/inbox.d.ts +28 -0
  98. package/agent-omp-sdk/dist/inbox.js +53 -0
  99. package/agent-omp-sdk/dist/index.d.ts +60 -0
  100. package/agent-omp-sdk/dist/index.js +632 -0
  101. package/agent-omp-sdk/dist/knobs.d.ts +34 -0
  102. package/agent-omp-sdk/dist/knobs.js +50 -0
  103. package/agent-omp-sdk/dist/lazy-rpc.d.ts +98 -0
  104. package/agent-omp-sdk/dist/lazy-rpc.js +178 -0
  105. package/agent-omp-sdk/dist/mobile/zoom-guard.d.ts +187 -0
  106. package/agent-omp-sdk/dist/mobile/zoom-guard.js +294 -0
  107. package/agent-omp-sdk/dist/mobile-boot.d.ts +49 -0
  108. package/agent-omp-sdk/dist/mobile-boot.js +38 -0
  109. package/agent-omp-sdk/dist/models.d.ts +39 -0
  110. package/agent-omp-sdk/dist/models.js +299 -0
  111. package/agent-omp-sdk/dist/omp-cli.d.ts +67 -0
  112. package/agent-omp-sdk/dist/omp-cli.js +164 -0
  113. package/agent-omp-sdk/dist/omp-disk-discovery.d.ts +27 -0
  114. package/agent-omp-sdk/dist/omp-disk-discovery.js +178 -0
  115. package/agent-omp-sdk/dist/omp-executable.d.ts +2 -0
  116. package/agent-omp-sdk/dist/omp-executable.js +30 -0
  117. package/agent-omp-sdk/dist/omp-store.d.ts +134 -0
  118. package/agent-omp-sdk/dist/omp-store.js +526 -0
  119. package/agent-omp-sdk/dist/pairing.d.ts +7 -0
  120. package/agent-omp-sdk/dist/pairing.js +45 -0
  121. package/agent-omp-sdk/dist/permission.d.ts +138 -0
  122. package/agent-omp-sdk/dist/permission.js +161 -0
  123. package/agent-omp-sdk/dist/protocol.d.ts +189 -0
  124. package/agent-omp-sdk/dist/rpc-types.d.ts +77 -0
  125. package/agent-omp-sdk/dist/rpc-types.js +1 -0
  126. package/agent-omp-sdk/dist/sdk-client.d.ts +160 -0
  127. package/{agent-omp → agent-omp-sdk}/dist/sdk-client.js +108 -56
  128. package/agent-omp-sdk/dist/sdk-runtime.d.ts +211 -0
  129. package/agent-omp-sdk/dist/sdk-runtime.js +418 -0
  130. package/agent-omp-sdk/dist/sidecar-client.d.ts +87 -0
  131. package/agent-omp-sdk/dist/sidecar-client.js +197 -0
  132. package/agent-omp-sdk/dist/store/adapter.d.ts +17 -0
  133. package/agent-omp-sdk/dist/store/adapter.js +47 -0
  134. package/agent-omp-sdk/dist/store/db.d.ts +70 -0
  135. package/agent-omp-sdk/dist/store/db.js +210 -0
  136. package/agent-omp-sdk/dist/store/index.d.ts +23 -0
  137. package/agent-omp-sdk/dist/store/index.js +59 -0
  138. package/agent-omp-sdk/dist/store/reconcile.d.ts +15 -0
  139. package/agent-omp-sdk/dist/store/reconcile.js +51 -0
  140. package/agent-omp-sdk/dist/store/schema.d.ts +8 -0
  141. package/agent-omp-sdk/dist/store/schema.js +40 -0
  142. package/agent-omp-sdk/dist/transport.d.ts +49 -0
  143. package/agent-omp-sdk/dist/transport.js +35 -0
  144. package/agent-omp-sdk/dist/world-home.d.ts +4 -0
  145. package/agent-omp-sdk/dist/world-home.js +23 -0
  146. package/agent-omp-sdk/dist/world-plugin.d.ts +10 -0
  147. package/agent-omp-sdk/dist/world-plugin.js +137 -0
  148. package/agent-omp-sdk/package.json +87 -0
  149. package/client/index.js +1794 -287
  150. package/cordis.patch.yml +80 -0
  151. package/package.json +23 -8
  152. package/superd-hub/dist/a2a-delivery.d.ts +189 -0
  153. package/superd-hub/dist/a2a-delivery.js +240 -0
  154. package/superd-hub/dist/a2a-host.d.ts +76 -0
  155. package/superd-hub/dist/a2a-host.js +145 -0
  156. package/superd-hub/dist/a2a-ingest.d.ts +31 -0
  157. package/superd-hub/dist/a2a-ingest.js +636 -0
  158. package/superd-hub/dist/a2a-log.d.ts +17 -0
  159. package/superd-hub/dist/a2a-log.js +42 -0
  160. package/superd-hub/dist/a2a-row.d.ts +65 -0
  161. package/superd-hub/dist/a2a-row.js +162 -0
  162. package/superd-hub/dist/a2a-service.d.ts +357 -0
  163. package/superd-hub/dist/a2a-service.js +980 -0
  164. package/superd-hub/dist/a2a-wire.d.ts +220 -0
  165. package/superd-hub/dist/a2a-wire.js +305 -0
  166. package/superd-hub/dist/agent-ids.d.ts +10 -0
  167. package/superd-hub/dist/agent-ids.js +68 -0
  168. package/superd-hub/dist/agent-roster.d.ts +29 -18
  169. package/superd-hub/dist/agent-roster.js +54 -15
  170. package/superd-hub/dist/agent-status.d.ts +119 -0
  171. package/superd-hub/dist/agent-status.js +386 -0
  172. package/superd-hub/dist/client/agent-settings.d.ts +156 -0
  173. package/superd-hub/dist/client/agent-settings.js +229 -0
  174. package/superd-hub/dist/client/mesh-api.d.ts +134 -0
  175. package/superd-hub/dist/client/mesh-api.js +219 -0
  176. package/superd-hub/dist/client/mesh-groups.d.ts +63 -0
  177. package/superd-hub/dist/client/mesh-groups.js +66 -0
  178. package/superd-hub/dist/client/roster.d.ts +48 -0
  179. package/superd-hub/dist/client/roster.js +102 -0
  180. package/superd-hub/dist/client/runtime-settings-api.d.ts +76 -0
  181. package/superd-hub/dist/client/runtime-settings-api.js +137 -0
  182. package/superd-hub/dist/client/switch.d.ts +165 -0
  183. package/superd-hub/dist/client/switch.js +295 -0
  184. package/superd-hub/dist/exec-pty-channel.d.ts +58 -0
  185. package/superd-hub/dist/exec-pty-channel.js +162 -0
  186. package/superd-hub/dist/exec-pty-framing.d.ts +32 -0
  187. package/superd-hub/dist/exec-pty-framing.js +81 -0
  188. package/superd-hub/dist/exec-pty-rpc.d.ts +21 -0
  189. package/superd-hub/dist/exec-pty-rpc.js +128 -0
  190. package/superd-hub/dist/exec-pty-session.d.ts +76 -0
  191. package/superd-hub/dist/exec-pty-session.js +234 -0
  192. package/superd-hub/dist/exec.d.ts +56 -0
  193. package/superd-hub/dist/exec.js +225 -0
  194. package/superd-hub/dist/gateway.d.ts +39 -2
  195. package/superd-hub/dist/gateway.js +62 -3
  196. package/superd-hub/dist/hub-tool.d.ts +174 -0
  197. package/superd-hub/dist/hub-tool.js +464 -0
  198. package/superd-hub/dist/index.d.ts +15 -1
  199. package/superd-hub/dist/index.js +16 -0
  200. package/superd-hub/dist/machines.d.ts +45 -0
  201. package/superd-hub/dist/machines.js +125 -0
  202. package/superd-hub/dist/mesh-federate.d.ts +138 -0
  203. package/superd-hub/dist/mesh-federate.js +223 -0
  204. package/superd-hub/dist/mesh-gateway.d.ts +67 -0
  205. package/superd-hub/dist/mesh-gateway.js +408 -0
  206. package/superd-hub/dist/mesh-link.d.ts +274 -0
  207. package/superd-hub/dist/mesh-link.js +441 -0
  208. package/superd-hub/dist/mesh-rpc.d.ts +123 -0
  209. package/superd-hub/dist/mesh-rpc.js +250 -0
  210. package/superd-hub/dist/mux-client.d.ts +71 -0
  211. package/superd-hub/dist/mux-client.js +281 -0
  212. package/superd-hub/dist/pack-version.d.ts +2 -0
  213. package/superd-hub/dist/pack-version.js +30 -0
  214. package/superd-hub/dist/roster.d.ts +6 -0
  215. package/superd-hub/dist/rpc.d.ts +18 -2
  216. package/superd-hub/dist/rpc.js +34 -4
  217. package/superd-hub/dist/spawn-world.js +3 -1
  218. package/superd-hub/dist/switch-core.d.ts +62 -25
  219. package/superd-hub/dist/switch-core.js +53 -30
  220. package/superd-hub/dist/system-head.d.ts +22 -12
  221. package/superd-hub/dist/system-head.js +100 -84
  222. package/superd-hub/dist/wire-endpoints.d.ts +264 -0
  223. package/superd-hub/dist/wire-endpoints.js +180 -0
  224. package/superd-hub/lib/client/index.js +1794 -287
  225. package/superd-hub/package.json +11 -2
  226. package/agent-agy/dist/agent-preset-projection.d.ts +0 -31
  227. package/agent-agy/dist/agent-preset-projection.js +0 -33
  228. package/agent-claude/dist/agent-preset-projection.js +0 -30
  229. package/agent-codex/dist/agent-preset-projection.js +0 -37
  230. package/agent-codex/dist/app-home.js +0 -65
  231. package/agent-codex/dist/models.js +0 -152
  232. package/agent-codex/dist/spike.js +0 -46
  233. package/agent-hermes/dist/agent-preset-projection.js +0 -34
  234. package/agent-omp/dist/agent-preset-projection.js +0 -36
  235. package/agent-omp/dist/app-home.js +0 -86
  236. package/agent-omp/dist/sidecar-client.js +0 -195
  237. package/agent-pi/dist/agent-preset-projection.js +0 -29
  238. package/superd-hub/dist/client-shim.d.ts +0 -28
  239. package/superd-hub/dist/client-shim.js +0 -251
  240. package/superd-hub/dist/index-pass.d.ts +0 -22
  241. package/superd-hub/dist/index-pass.js +0 -47
  242. package/superd-hub/dist/labels.d.ts +0 -45
  243. package/superd-hub/dist/labels.js +0 -83
  244. /package/{agent-agy → agent-agy-sdk}/bridge/agy_bridge.py +0 -0
  245. /package/{agent-agy → agent-agy-sdk}/bridge/gemini_openai_server.mjs +0 -0
  246. /package/{agent-codex/dist/codex-events.js → agent-codex-sdk/dist/codex-sdk-events.js} +0 -0
  247. /package/{agent-omp → agent-omp-sdk}/dist/protocol.js +0 -0
  248. /package/{agent-omp → agent-omp-sdk}/sidecar/main.ts +0 -0
package/cordis.patch.yml CHANGED
@@ -21,6 +21,10 @@
21
21
  # On/off: row `disabled: true`, or config
22
22
  # `trustedPageAuthorities: []` (inert). Default
23
23
  # derives from the trusted-hosts env.
24
+ # - super-dsh/a2a the agent-facing A2A tool face (mesh P3): the
25
+ # single `superd-hub` model tool on ctx0's tools
26
+ # service (dormant without tools; world trees
27
+ # never compose this row — see a2a-row.ts).
24
28
  #
25
29
  # Profile-layer values (webserver port/host, settings path) stay in the USER's
26
30
  # profile patch layer, never here.
@@ -45,6 +49,18 @@
45
49
  # composition. Off = the component registers nothing: no script, no global.
46
50
  - id: superd-fusion-transport
47
51
  name: 'super-dsh/fusion-transport'
52
+ # A2A tool face (mesh P3 Task 4): composes the single model-facing
53
+ # `superd-hub` tool onto ctx0's tools service and closes the a2a-host
54
+ # nativeGateway seam with the hub process's own typertGateway. Subpath row
55
+ # BY RULING (a2a-row.ts header): world trees provide a tools service too,
56
+ # so riding the bare superd-hub row would mount a mis-wired tool inside
57
+ # every world; this row lives only HERE, which world profiles never
58
+ # compose — ctx0 only, exactly the P3 initiator surface (foreign runtimes
59
+ # get their own injection in P5, spec §10). Dormant without tools.
60
+ # Off: restate with `disabled: true` or drop the row — nothing else
61
+ # registers the tool.
62
+ - id: superd-a2a
63
+ name: 'super-dsh/a2a'
48
64
  - id: agent-omp
49
65
  name: 'super-dsh/agents/omp'
50
66
  - id: agent-codex
@@ -55,6 +71,70 @@
55
71
  name: 'super-dsh/agents/hermes'
56
72
  - id: agent-agy
57
73
  name: 'super-dsh/agents/agy'
74
+ # Opt-IN SDK half of the Antigravity split (2026-10-02 user ruling). The
75
+ # CLI row above is the PRIMARY path: the user already runs Antigravity, so
76
+ # the CLI reuses that environment (their ~/.gemini, ADC and keyring) for
77
+ # free, while this row drives the Python `google-antigravity` SDK instead.
78
+ #
79
+ # DISABLED BY DEFAULT — turning the row on IS the switch
80
+ # (`plugin-presence IS the roster`): no env var, no config key. It runs as
81
+ # world key `agy-sdk` (roster label "Antigravity (SDK)", world home
82
+ # `agents/agy-sdk`), deliberately distinct from `agy` because the hub's
83
+ # registerAgent hard-throws on a duplicate key and this row ships beside
84
+ # the CLI row — the two can therefore both be enabled harmlessly.
85
+ #
86
+ # No Python is installed at `dsh plugin add` time and this package declares
87
+ # no SDK dependency: the durable venv is fetched into that world home on
88
+ # first real use (agent-agy-sdk/src/sdk-venv.ts).
89
+ - id: agent-agy-sdk
90
+ name: 'super-dsh/agents/agy-sdk'
91
+ disabled: true
92
+ # Opt-IN SDK transport for OMP (2026-10-03 user ruling). `agent-omp` is the
93
+ # PRIMARY path: it drives the operator's own `omp` binary, so the plugin
94
+ # ships no runtime at all. This row drives the SAME agent through the
95
+ # package's in-process SDK face instead — one bun sidecar hosting every
96
+ # session (shared authStorage/modelRegistry), which is the cheaper memory
97
+ # shape for many concurrent sessions, at the cost of fetching a ~900 MB
98
+ # runtime tree.
99
+ #
100
+ # DISABLED BY DEFAULT — turning the row on IS the switch
101
+ # (`plugin-presence IS the roster`): no env var, no config key. It runs as
102
+ # world key `omp-sdk` (roster label "OMP (SDK)", world home
103
+ # `agents/omp-sdk`), deliberately distinct from `omp` because the hub's
104
+ # registerAgent hard-throws on a duplicate key and this row ships beside
105
+ # the RPC row — the two can therefore both be enabled harmlessly.
106
+ #
107
+ # Nothing is installed at `dsh plugin add` time and this package declares no
108
+ # dependency: the durable bun runtime + `@oh-my-pi/pi-coding-agent` tree is
109
+ # fetched into that world home on first real use
110
+ # (agent-omp-sdk/src/sdk-runtime.ts).
111
+ - id: agent-omp-sdk
112
+ name: 'super-dsh/agents/omp-sdk'
113
+ disabled: true
114
+ # PRESERVED SDK line for Codex (2026-10-04 user ruling). `agent-codex` is the
115
+ # PRIMARY path — it drives a `codex app-server` child process, so the plugin
116
+ # bundles no SDK: the CLI the operator already has is the runtime. This row
117
+ # drives the SAME agent through the older in-process `@openai/codex-sdk` face
118
+ # instead, kept because the code was already written and it is a real option
119
+ # (no child process per session, and it works with no `codex` binary on PATH
120
+ # once its runtime is fetched).
121
+ #
122
+ # DISABLED BY DEFAULT — turning the row on IS the switch (`plugin-presence IS
123
+ # the roster`): no env var, no config key. It runs as world key `codex-sdk`
124
+ # (roster label "Codex (SDK)", world home `agents/codex-sdk`), deliberately
125
+ # distinct from `codex` because the hub's registerAgent hard-throws on a
126
+ # duplicate key and this row ships beside the app-server row — the two can
127
+ # therefore both be enabled harmlessly.
128
+ #
129
+ # Nothing is installed at `dsh plugin add` time and this package declares NO
130
+ # dependency — not a dependency, not an optionalDependency, not a peer: the
131
+ # SDK tree (`@openai/codex-sdk` + the codex binary package, pinned together)
132
+ # is fetched into that world home on the first real prompt and is durable
133
+ # there (agent-codex-sdk/src/sdk-runtime.ts; pre-warm with
134
+ # `npm run fetch-sdk-runtime`). Zero-spawn, zero-download window before it.
135
+ - id: agent-codex-sdk
136
+ name: 'super-dsh/agents/codex-sdk'
137
+ disabled: true
58
138
  # R2 (2026-09-16): the claude adapter ships STANDALONE only — its /world
59
139
  # entry is inert. The HUB side joins it: one generic joiner row with the
60
140
  # key; spawn/roster/mount wiring lives in super-dsh/join.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "super-dsh",
3
- "version": "0.1.6",
4
- "description": "Super D for the DeepSeek Harness (DSH) — one dsh plugin that mounts the superd hub (runtime selector, roster, per-runtime agents) and joins local foreign-agent runtimes (OMP, Codex, Claude, Pi, Hermes, Antigravity) into the DSH Web UI. Each runtime keeps its native home and session store; the hub only bridges.",
3
+ "version": "0.1.10",
4
+ "description": "Super D for the DeepSeek Harness (DSH) \u2014 one dsh plugin that mounts the superd hub (runtime selector, roster, per-runtime agents) and joins local foreign-agent runtimes (OMP, Codex, Claude, Pi, Hermes, Antigravity) into the DSH Web UI. Each runtime keeps its native home and session store; the hub only bridges.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -18,11 +18,15 @@
18
18
  "./agents/pi": "./agent-pi/dist/world-plugin.js",
19
19
  "./agents/hermes": "./agent-hermes/dist/world-plugin.js",
20
20
  "./agents/agy": "./agent-agy/dist/world-plugin.js",
21
+ "./agents/agy-sdk": "./agent-agy-sdk/dist/world-plugin.js",
22
+ "./agents/omp-sdk": "./agent-omp-sdk/dist/world-plugin.js",
23
+ "./agents/codex-sdk": "./agent-codex-sdk/dist/world-plugin.js",
21
24
  "./client": "./client/index.js",
22
25
  "./cordis.patch.yml": "./cordis.patch.yml",
23
26
  "./package.json": "./package.json",
24
27
  "./web-trust": "./superd-hub/dist/web-trust.js",
25
- "./fusion-transport": "./superd-hub/dist/fusion-transport.js"
28
+ "./fusion-transport": "./superd-hub/dist/fusion-transport.js",
29
+ "./a2a": "./superd-hub/dist/a2a-row.js"
26
30
  },
27
31
  "files": [
28
32
  "cordis.patch.yml",
@@ -35,10 +39,17 @@
35
39
  "agent-omp/dist",
36
40
  "agent-omp/package.json",
37
41
  "agent-omp/cordis.patch.yml",
38
- "agent-omp/sidecar",
42
+ "agent-omp-sdk/dist",
43
+ "agent-omp-sdk/sidecar",
44
+ "agent-omp-sdk/package.json",
45
+ "agent-omp-sdk/cordis.patch.yml",
39
46
  "agent-codex/dist",
40
47
  "agent-codex/package.json",
41
48
  "agent-codex/cordis.patch.yml",
49
+ "agent-codex-sdk/dist",
50
+ "agent-codex-sdk/scripts",
51
+ "agent-codex-sdk/package.json",
52
+ "agent-codex-sdk/cordis.patch.yml",
42
53
  "agent-claude/dist",
43
54
  "agent-claude/package.json",
44
55
  "agent-claude/cordis.patch.yml",
@@ -51,7 +62,10 @@
51
62
  "agent-agy/dist",
52
63
  "agent-agy/package.json",
53
64
  "agent-agy/cordis.patch.yml",
54
- "agent-agy/bridge"
65
+ "agent-agy-sdk/dist",
66
+ "agent-agy-sdk/package.json",
67
+ "agent-agy-sdk/cordis.patch.yml",
68
+ "agent-agy-sdk/bridge"
55
69
  ],
56
70
  "dsh": {
57
71
  "bundle": {
@@ -67,10 +81,7 @@
67
81
  "dependencies": {
68
82
  "@anthropic-ai/claude-agent-sdk": "0.3.263",
69
83
  "@earendil-works/pi-coding-agent": "0.84.2",
70
- "@oh-my-pi/pi-coding-agent": "^18.1.14",
71
84
  "@openai/codex": "0.154.0",
72
- "@openai/codex-sdk": "0.154.0",
73
- "bun": "^1.4.2",
74
85
  "ws": "^8.21.0",
75
86
  "zod": "4.4.3",
76
87
  "@modelcontextprotocol/sdk": "^1.29.0"
@@ -87,6 +98,7 @@
87
98
  "@deepseek-ai/dsh-scope": ">=0.1.5-0 <0.3.0-0",
88
99
  "@deepseek-ai/dsh-session": ">=0.1.5-0 <0.3.0-0",
89
100
  "@deepseek-ai/dsh-session-persistence": ">=0.1.5-0 <0.3.0-0",
101
+ "@deepseek-ai/dsh-tools": ">=0.1.5-0 <0.3.0-0",
90
102
  "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-0 <0.3.0-0",
91
103
  "@deepseek-ai/dsh-user-approval": ">=0.1.5-0 <0.3.0-0",
92
104
  "@deepseek-ai/dsh-user-questions": ">=0.1.5-0 <0.3.0-0"
@@ -125,6 +137,9 @@
125
137
  "@deepseek-ai/dsh-session-persistence": {
126
138
  "optional": true
127
139
  },
140
+ "@deepseek-ai/dsh-tools": {
141
+ "optional": true
142
+ },
128
143
  "@deepseek-ai/dsh-typert-protocol": {
129
144
  "optional": true
130
145
  },
@@ -0,0 +1,189 @@
1
+ import type { ContentBlock } from '@deepseek-ai/dsh-llm';
2
+ import { A2A_NOTICE_SUMMARY_MAX, type A2aNoticeReason } from './a2a-wire.js';
3
+ export { A2A_NOTICE_SUMMARY_MAX, type A2aNoticeReason };
4
+ import type { A2aConversationRef, A2aInitiator, A2aService } from './a2a-service.js';
5
+ /** Durable attribution for one peer reply relayed into the initiator's conversation. */
6
+ export interface A2aRelaySource {
7
+ readonly kind: 'a2a-relay';
8
+ /** A message another agent addressed to this one (`relay` context form). */
9
+ readonly form: 'relay';
10
+ /** Machine id (m4) of the replying peer. */
11
+ readonly senderMachine: string;
12
+ /** Agent id (a6) of the replying peer. */
13
+ readonly senderAgent: string;
14
+ /** Conversation shortId the reply belongs to. */
15
+ readonly conversationId: string;
16
+ /** Durable identity of this relay (minted at delivery, one per fired completion). */
17
+ readonly messageId: string;
18
+ }
19
+ /** Why a runtime-owned notice was produced — the taxonomy now lives on the
20
+ * protocol layer (a2a-wire.ts, imported + re-exported above): 0.1.7-h R2
21
+ * made it a wire fact, and the model-facing notice line renders it. */
22
+ /**
23
+ * Durable attribution for the hub's own account of an A2A conversation event
24
+ * (a failed send, a dead completion stream, a stop) — deliberately a notice,
25
+ * not a relay: the hub states what became of the conversation and never
26
+ * credits the peer with words it did not write.
27
+ */
28
+ export interface A2aNoticeSource {
29
+ readonly kind: 'a2a-notice';
30
+ /** A runtime account shown without expanding the row (`notice` context form). */
31
+ readonly form: 'notice';
32
+ /** One-line account of what happened, bounded to {@link A2A_NOTICE_SUMMARY_MAX}. */
33
+ readonly summary: string;
34
+ /** Conversation shortId the notice is about, when one is known. */
35
+ readonly conversationId?: string;
36
+ /** Which failure this notice reports. */
37
+ readonly reason: A2aNoticeReason;
38
+ }
39
+ declare module '@deepseek-ai/dsh-llm' {
40
+ interface MessageSourceMap {
41
+ 'a2a-relay': A2aRelaySource;
42
+ 'a2a-notice': A2aNoticeSource;
43
+ }
44
+ }
45
+ /** Bound for a notice summary — owned by a2a-wire.ts since R1 (see the re-export above). */
46
+ /**
47
+ * Bound one notice summary to {@link A2A_NOTICE_SUMMARY_MAX} — the same
48
+ * ellipsizing as upstream `boundContextSummary` (dsh-llm message.ts).
49
+ * @param summary - the producer's one-line account, of any length.
50
+ * @returns the account, ellipsized when it exceeds the bound.
51
+ */
52
+ export declare function boundNoticeSummary(summary: string): string;
53
+ /** Reply-routing choice over `ctx.agents`; peer semantics default to followup (spec §7.3). */
54
+ export type A2aReplyDelivery = 'followup' | 'steer';
55
+ /** One delivered (or buffered) reply/notice outcome. */
56
+ export type A2aDeliveryOutcome = {
57
+ delivered: 'followup';
58
+ } | {
59
+ delivered: 'steer';
60
+ } | {
61
+ delivered: 'buffered';
62
+ } | {
63
+ delivered: 'dropped';
64
+ reason: 'no-conversation';
65
+ };
66
+ /** Structural mirror of upstream `createUserMessage` output (dsh-llm message.ts) —
67
+ * fresh identity, role 'user', content blocks, producer source; detached and
68
+ * deep-frozen before publication. The id mirrors upstream's branded MessageId
69
+ * as a plain string (brands are compile-time only; the hub keeps zero dsh-llm
70
+ * runtime dependencies). */
71
+ export interface A2aDeliveredMessage {
72
+ readonly id: string;
73
+ readonly role: 'user';
74
+ readonly content: readonly ContentBlock[];
75
+ readonly source: A2aRelaySource | A2aNoticeSource;
76
+ }
77
+ /**
78
+ * The agent-handle face this layer consumes — structural subset of upstream
79
+ * `Agent` (packages/core/agent/src/runtime-types.ts): lifecycle status plus
80
+ * the three inbox boundaries followup / steer / inject.
81
+ */
82
+ export interface A2aAgentHandle {
83
+ /** Lifecycle state ('idle' | 'running' upstream); peer routing does NOT branch on it. */
84
+ readonly status: string;
85
+ followup(message: A2aDeliveredMessage): void;
86
+ steer(message: A2aDeliveredMessage): void;
87
+ inject(message: A2aDeliveredMessage): void;
88
+ }
89
+ /**
90
+ * The delivery context: the live-agent registry face plus Task 2's bounded
91
+ * unread-buffer leg (the persistence policy for initiators that are not live).
92
+ */
93
+ export interface A2aDeliveryCtx {
94
+ /** Structural subset of `ctx.agents` (AgentRegistry): `get` → live handle or undefined. */
95
+ readonly agents: {
96
+ get(sessionId: string): A2aAgentHandle | undefined;
97
+ };
98
+ /** Task 2's `A2aService.buffer` leg — where undeliverable messages wait. */
99
+ readonly buffer: A2aService['buffer'];
100
+ }
101
+ /** Producer attribution for one relayed peer reply. */
102
+ export interface A2aReplyMeta {
103
+ senderMachine: string;
104
+ senderAgent: string;
105
+ /** Conversation shortId the reply belongs to. */
106
+ conversationId: string;
107
+ /** Durable identity of this relay (one per fired completion). */
108
+ messageId: string;
109
+ /** Conversation title for the relay prefix (untitled placeholder when absent). */
110
+ title?: string;
111
+ /** D20: true = the runtime's transcription of the peer's turn-end last output (the peer never sent it through the channel) — renders the provenance prefix instead of "replied". */
112
+ transcribed?: boolean;
113
+ }
114
+ /** Producer attribution for one runtime notice. */
115
+ export interface A2aNoticeMeta {
116
+ senderMachine: string;
117
+ senderAgent: string;
118
+ /** Conversation shortId the notice is about; absent notices cannot buffer. */
119
+ conversationId?: string;
120
+ reason: A2aNoticeReason;
121
+ }
122
+ /**
123
+ * The model-facing reply envelope (0.1.7-h R1 — one stable machine-readable
124
+ * vocabulary, replacing the v3 prose prefixes per the operator's §8 ruling:
125
+ * provenance the model had to recover from English sentences is now stated):
126
+ * a header line of `k=v` facts, a blank line, then the reply body. `form`
127
+ * keeps the D20 provenance split — `relay` = the peer chose to send through
128
+ * the channel; `transcript` = the peer never sent, the runtime is delivering
129
+ * its last output at turn end (the note spells out that observable fact per
130
+ * the user's no-jargon redline).
131
+ * @param meta - the reply attribution.
132
+ * @param content - the reply text (channel message or transcribed last output).
133
+ * @returns `[superd-hub:a2a] kind=reply form=… conversation=… from=… message=…[ note="…"]\n\n<body>`.
134
+ */
135
+ export declare function renderA2aRelayText(meta: A2aReplyMeta, content: string): string;
136
+ /** R2: the three model-facing cause values — one wire fact maps to exactly one
137
+ * model value, so the notice line and its summary can never disagree. */
138
+ export type A2aModelNoticeReason = 'peer-silent' | 'peer-error' | 'stopped-by-initiator' | 'delivered' | 'undelivered';
139
+ /** Map the wire cause taxonomy onto the model-facing one. */
140
+ export declare function modelNoticeReason(reason: A2aNoticeReason): A2aModelNoticeReason;
141
+ /**
142
+ * Render the model-visible notice text (0.1.7-h R1/R2): ONE line in the same
143
+ * envelope vocabulary as relays, plus the R2 cause and the bounded summary.
144
+ * Inner double quotes are sanitized to single quotes (legacy peer summaries
145
+ * embed `conversation "x"`) so the k=v line stays parseable; the wire/source
146
+ * summary keeps its verbatim text.
147
+ */
148
+ export declare function renderA2aNoticeText(meta: A2aNoticeMeta, summary: string): string;
149
+ /**
150
+ * Deliver one peer reply into the initiating agent's conversation.
151
+ * @param ctx - live-agent face + buffer leg.
152
+ * @param initiator - who asked (its sessionId keys the buffer).
153
+ * @param content - the peer's final reply text.
154
+ * @param meta - relay attribution (sender address, conversation, identity, title).
155
+ * @param opts - `delivery:'steer'` overrides the followup default.
156
+ * @returns where the reply landed.
157
+ */
158
+ export declare function deliverReply(ctx: A2aDeliveryCtx, initiator: A2aInitiator, content: string, meta: A2aReplyMeta, opts?: {
159
+ delivery?: A2aReplyDelivery;
160
+ }): A2aDeliveryOutcome;
161
+ /**
162
+ * Deliver one runtime-owned notice (bounded one-line account) into the
163
+ * initiating agent's conversation.
164
+ * @param ctx - live-agent face + buffer leg.
165
+ * @param initiator - who asked (its sessionId keys the buffer).
166
+ * @param summary - the one-line account, any length (bounded here).
167
+ * @param meta - notice attribution; a notice without a conversation cannot buffer.
168
+ * @param opts - `delivery:'steer'` overrides the followup default.
169
+ * @returns where the notice landed.
170
+ */
171
+ export declare function deliverNotice(ctx: A2aDeliveryCtx, initiator: A2aInitiator, summary: string, meta: A2aNoticeMeta, opts?: {
172
+ delivery?: A2aReplyDelivery;
173
+ }): A2aDeliveryOutcome;
174
+ /** The Task-2 service surface the glue consumes. */
175
+ export type A2aCompletionSource = Pick<A2aService, 'subscribeCompletion' | 'listConversations'>;
176
+ /**
177
+ * Wire one conversation's completion stream to the initiator's delivery face:
178
+ * every fired completion becomes one relayed reply (titled from the registry
179
+ * row); a completion-stream death becomes one bounded stream-dead notice.
180
+ * Wire one conversation's completion stream to the initiator's delivery face:
181
+ * every fired completion becomes one relayed reply (titled from the registry
182
+ * row) — EXCEPT a turn that ended non-completed with NO captured text, which
183
+ * degrades to a bounded 'aborted' notice (D3: a content-free relay is noise
184
+ * and can wake an idle initiator for nothing); a completion-stream death
185
+ * becomes one bounded stream-dead notice.
186
+ */
187
+ export declare function wireCompletionToDelivery(ctx: A2aDeliveryCtx, service: A2aCompletionSource, initiator: A2aInitiator, conv: A2aConversationRef, opts?: {
188
+ requestId?: string;
189
+ }): () => void;
@@ -0,0 +1,240 @@
1
+ /**
2
+ * A2A reply-delivery face (mesh P3 Task 3): how a peer agent's reply arrives
3
+ * back in the INITIATING agent's conversation — the two producer source kinds
4
+ * for `@deepseek-ai/dsh-llm`'s MessageSourceMap, the peer-routing rules over
5
+ * `ctx.agents`, and the subscribe→deliver glue.
6
+ *
7
+ * Upstream anchors (`upstream/deepseek-harness` @ dsh-v0.1.7-rc.1):
8
+ * - the continuation-message pattern: `packages/subagent/subagent/src/
9
+ * continuation-messages.ts` — each producer declares its own kinds into
10
+ * MessageSourceMap via `declare module '@deepseek-ai/dsh-llm'` with a
11
+ * type-only import of the target package, and builds user-role messages
12
+ * through `createUserMessage` (fresh identity, detached, deep-frozen).
13
+ * That constructor is not re-exported by any package the hub may consume,
14
+ * so this module constructs the SAME structural shape locally
15
+ * ({@link A2aDeliveredMessage}) and keeps a zero-dependency runtime —
16
+ * the type-only import below anchors the augmentation exactly like the
17
+ * upstream precedent.
18
+ * - the delivery routing template: `continuation-activation.ts`
19
+ * notifySettlement (:871-888) — idle→queue, busy→steer, closing
20
+ * teardown→inject, missing→nothing. That is the PARENT/child contract.
21
+ * A2A peers are not parents (spec §7.3 ruling): a peer reply is ordinary
22
+ * queued input, so idle AND busy both deliver via `followup` — never
23
+ * interrupting the initiator's active turn — and `steer` exists ONLY for
24
+ * explicit `delivery:'steer'` requests; a missing initiator (not live,
25
+ * torn down) lands in Task 2's bounded unread buffer instead of being
26
+ * injected or dropped.
27
+ * - notice summaries are bounded like upstream `boundContextSummary`
28
+ * (CONTEXT_SUMMARY_MAX_CHARS = 120): 119 chars + '…'.
29
+ */
30
+ import { randomUUID } from 'node:crypto';
31
+ import { A2A_NOTICE_SUMMARY_MAX } from './a2a-wire.js';
32
+ // compat re-exports (postoffice R1 / 0.1.7-h R2): both moved to the protocol
33
+ // layer (a2a-wire.ts) — the bound so the envelope guard enforces the same
34
+ // number this module bounds with, the reason type because it now crosses the
35
+ // wire; existing importers keep compiling.
36
+ export { A2A_NOTICE_SUMMARY_MAX };
37
+ /** Bound for a notice summary — owned by a2a-wire.ts since R1 (see the re-export above). */
38
+ /**
39
+ * Bound one notice summary to {@link A2A_NOTICE_SUMMARY_MAX} — the same
40
+ * ellipsizing as upstream `boundContextSummary` (dsh-llm message.ts).
41
+ * @param summary - the producer's one-line account, of any length.
42
+ * @returns the account, ellipsized when it exceeds the bound.
43
+ */
44
+ export function boundNoticeSummary(summary) {
45
+ return summary.length <= A2A_NOTICE_SUMMARY_MAX
46
+ ? summary
47
+ : `${summary.slice(0, A2A_NOTICE_SUMMARY_MAX - 1)}…`;
48
+ }
49
+ /** Recursive freeze, mirroring upstream `deepFreeze(structuredClone(...))` publication. */
50
+ function deepFreeze(value) {
51
+ if (value !== null && typeof value === 'object') {
52
+ if (Array.isArray(value)) {
53
+ for (const item of value)
54
+ deepFreeze(item);
55
+ }
56
+ else {
57
+ for (const key of Object.keys(value))
58
+ deepFreeze(value[key]);
59
+ }
60
+ Object.freeze(value);
61
+ }
62
+ return value;
63
+ }
64
+ /**
65
+ * Build one identified, immutable user-role message — the local equivalent of
66
+ * upstream `createUserMessage`: fresh uuid identity, structuredClone-detached,
67
+ * deep-frozen before publication.
68
+ * @param content - model-visible message blocks.
69
+ * @param source - the producer attribution (our declared kinds).
70
+ * @returns the frozen user message handed to the initiator's inbox.
71
+ */
72
+ function createA2aUserMessage(content, source) {
73
+ return deepFreeze(structuredClone({
74
+ id: randomUUID(),
75
+ role: 'user',
76
+ content,
77
+ source,
78
+ }));
79
+ }
80
+ /**
81
+ * The model-facing reply envelope (0.1.7-h R1 — one stable machine-readable
82
+ * vocabulary, replacing the v3 prose prefixes per the operator's §8 ruling:
83
+ * provenance the model had to recover from English sentences is now stated):
84
+ * a header line of `k=v` facts, a blank line, then the reply body. `form`
85
+ * keeps the D20 provenance split — `relay` = the peer chose to send through
86
+ * the channel; `transcript` = the peer never sent, the runtime is delivering
87
+ * its last output at turn end (the note spells out that observable fact per
88
+ * the user's no-jargon redline).
89
+ * @param meta - the reply attribution.
90
+ * @param content - the reply text (channel message or transcribed last output).
91
+ * @returns `[superd-hub:a2a] kind=reply form=… conversation=… from=… message=…[ note="…"]\n\n<body>`.
92
+ */
93
+ export function renderA2aRelayText(meta, content) {
94
+ const header = meta.transcribed === true
95
+ ? `[superd-hub:a2a] kind=reply form=transcript conversation=${meta.conversationId} from=${meta.senderMachine}-${meta.senderAgent} message=${meta.messageId} note="the peer never sent through the channel — this is the runtime delivering the peer's last output at turn end"`
96
+ : `[superd-hub:a2a] kind=reply form=relay conversation=${meta.conversationId} from=${meta.senderMachine}-${meta.senderAgent} message=${meta.messageId}`;
97
+ return `${header}\n\n${content}`;
98
+ }
99
+ /** Map the wire cause taxonomy onto the model-facing one. */
100
+ export function modelNoticeReason(reason) {
101
+ switch (reason) {
102
+ case 'stop': return 'stopped-by-initiator';
103
+ case 'peer': return 'peer-silent';
104
+ case 'delivered': return 'delivered';
105
+ case 'undelivered': return 'undelivered';
106
+ default: return 'peer-error'; // send-failed / stream-dead / aborted — the peer side ended abnormally
107
+ }
108
+ }
109
+ /**
110
+ * Render the model-visible notice text (0.1.7-h R1/R2): ONE line in the same
111
+ * envelope vocabulary as relays, plus the R2 cause and the bounded summary.
112
+ * Inner double quotes are sanitized to single quotes (legacy peer summaries
113
+ * embed `conversation "x"`) so the k=v line stays parseable; the wire/source
114
+ * summary keeps its verbatim text.
115
+ */
116
+ export function renderA2aNoticeText(meta, summary) {
117
+ const conv = meta.conversationId === undefined ? '' : ` conversation=${meta.conversationId}`;
118
+ return `[superd-hub:a2a] kind=notice${conv} from=${meta.senderMachine}-${meta.senderAgent} reason=${modelNoticeReason(meta.reason)} summary="${summary.replace(/"/g, "'")}"`;
119
+ }
120
+ /**
121
+ * Route one built message to the initiator: live → followup (or steer when
122
+ * explicitly requested); not live → the buffer leg when the input has a
123
+ * conversation to anchor it, else best-effort nothing.
124
+ */
125
+ function route(ctx, initiator, message, delivery, buffered) {
126
+ const agent = ctx.agents.get(initiator.sessionId);
127
+ if (agent === undefined) {
128
+ if (buffered === undefined)
129
+ return { delivered: 'dropped', reason: 'no-conversation' };
130
+ ctx.buffer(initiator.sessionId, buffered);
131
+ return { delivered: 'buffered' };
132
+ }
133
+ if (delivery === 'steer')
134
+ agent.steer(message);
135
+ else
136
+ agent.followup(message);
137
+ return { delivered: delivery };
138
+ }
139
+ /**
140
+ * Deliver one peer reply into the initiating agent's conversation.
141
+ * @param ctx - live-agent face + buffer leg.
142
+ * @param initiator - who asked (its sessionId keys the buffer).
143
+ * @param content - the peer's final reply text.
144
+ * @param meta - relay attribution (sender address, conversation, identity, title).
145
+ * @param opts - `delivery:'steer'` overrides the followup default.
146
+ * @returns where the reply landed.
147
+ */
148
+ export function deliverReply(ctx, initiator, content, meta, opts = {}) {
149
+ const text = renderA2aRelayText(meta, content);
150
+ const message = createA2aUserMessage([{ type: 'text', text }], {
151
+ kind: 'a2a-relay',
152
+ form: 'relay',
153
+ senderMachine: meta.senderMachine,
154
+ senderAgent: meta.senderAgent,
155
+ conversationId: meta.conversationId,
156
+ messageId: meta.messageId,
157
+ });
158
+ return route(ctx, initiator, message, opts.delivery ?? 'followup', {
159
+ messageId: meta.messageId,
160
+ from: { machine: meta.senderMachine, id: meta.senderAgent },
161
+ conversationId: meta.conversationId,
162
+ text,
163
+ });
164
+ }
165
+ /**
166
+ * Deliver one runtime-owned notice (bounded one-line account) into the
167
+ * initiating agent's conversation.
168
+ * @param ctx - live-agent face + buffer leg.
169
+ * @param initiator - who asked (its sessionId keys the buffer).
170
+ * @param summary - the one-line account, any length (bounded here).
171
+ * @param meta - notice attribution; a notice without a conversation cannot buffer.
172
+ * @param opts - `delivery:'steer'` overrides the followup default.
173
+ * @returns where the notice landed.
174
+ */
175
+ export function deliverNotice(ctx, initiator, summary, meta, opts = {}) {
176
+ const bounded = boundNoticeSummary(summary);
177
+ // R1: a notice is an injected turn like any other — its model-facing text
178
+ // is the envelope line (provenance + cause + summary); the buffered copy
179
+ // carries the same line so a later sweep injects identical text.
180
+ const noticeText = renderA2aNoticeText(meta, bounded);
181
+ const message = createA2aUserMessage([{ type: 'text', text: noticeText }], {
182
+ kind: 'a2a-notice',
183
+ form: 'notice',
184
+ summary: bounded,
185
+ ...(meta.conversationId === undefined ? {} : { conversationId: meta.conversationId }),
186
+ reason: meta.reason,
187
+ });
188
+ const buffered = meta.conversationId === undefined ? undefined : {
189
+ messageId: `a2a-notice-${randomUUID()}`,
190
+ from: { machine: meta.senderMachine, id: meta.senderAgent },
191
+ conversationId: meta.conversationId,
192
+ text: noticeText,
193
+ };
194
+ return route(ctx, initiator, message, opts.delivery ?? 'followup', buffered);
195
+ }
196
+ /**
197
+ * Wire one conversation's completion stream to the initiator's delivery face:
198
+ * every fired completion becomes one relayed reply (titled from the registry
199
+ * row); a completion-stream death becomes one bounded stream-dead notice.
200
+ * Wire one conversation's completion stream to the initiator's delivery face:
201
+ * every fired completion becomes one relayed reply (titled from the registry
202
+ * row) — EXCEPT a turn that ended non-completed with NO captured text, which
203
+ * degrades to a bounded 'aborted' notice (D3: a content-free relay is noise
204
+ * and can wake an idle initiator for nothing); a completion-stream death
205
+ * becomes one bounded stream-dead notice.
206
+ */
207
+ export function wireCompletionToDelivery(ctx, service, initiator, conv, opts = {}) {
208
+ const titleOf = (conversationId) => service.listConversations().find((r) => r.shortId === conversationId || r.sessionId === conversationId)?.title;
209
+ return service.subscribeCompletion(conv, (completion) => {
210
+ // D3: a terminal turn that produced NO reply must not relay — aborted
211
+ // WITH captured text still relays (the words exist); only the empty
212
+ // non-completed end becomes a bounded notice.
213
+ if (completion.reason !== 'completed' && completion.text === '') {
214
+ deliverNotice(ctx, initiator, `conversation ${completion.conversationId}: turn aborted, no reply`, {
215
+ senderMachine: conv.to.machine,
216
+ senderAgent: conv.to.id,
217
+ conversationId: completion.conversationId,
218
+ reason: 'aborted',
219
+ });
220
+ return;
221
+ }
222
+ deliverReply(ctx, initiator, completion.text, {
223
+ senderMachine: conv.to.machine,
224
+ senderAgent: conv.to.id,
225
+ conversationId: completion.conversationId,
226
+ messageId: `a2a-relay-${randomUUID()}`,
227
+ title: titleOf(completion.conversationId),
228
+ });
229
+ }, {
230
+ requestId: opts.requestId,
231
+ onError: (error) => {
232
+ deliverNotice(ctx, initiator, `A2A completion stream from ${conv.to.machine}-${conv.to.id} (conversation "${conv.conversationId}") failed: ${error.message}`, {
233
+ senderMachine: conv.to.machine,
234
+ senderAgent: conv.to.id,
235
+ conversationId: conv.conversationId,
236
+ reason: 'stream-dead',
237
+ });
238
+ },
239
+ });
240
+ }