@krischoichoi/channel-harness 0.6.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 (202) hide show
  1. package/README.md +110 -0
  2. package/lib/access/controller.d.ts +37 -0
  3. package/lib/access/controller.d.ts.map +1 -0
  4. package/lib/access/controller.js +51 -0
  5. package/lib/access/controller.js.map +1 -0
  6. package/lib/access/decision.d.ts +18 -0
  7. package/lib/access/decision.d.ts.map +1 -0
  8. package/lib/access/decision.js +2 -0
  9. package/lib/access/decision.js.map +1 -0
  10. package/lib/access/resolver.d.ts +41 -0
  11. package/lib/access/resolver.d.ts.map +1 -0
  12. package/lib/access/resolver.js +31 -0
  13. package/lib/access/resolver.js.map +1 -0
  14. package/lib/agent-manager.d.ts +314 -0
  15. package/lib/agent-manager.d.ts.map +1 -0
  16. package/lib/agent-manager.js +603 -0
  17. package/lib/agent-manager.js.map +1 -0
  18. package/lib/agent-router.d.ts +37 -0
  19. package/lib/agent-router.d.ts.map +1 -0
  20. package/lib/agent-router.js +33 -0
  21. package/lib/agent-router.js.map +1 -0
  22. package/lib/bind-support.d.ts +23 -0
  23. package/lib/bind-support.d.ts.map +1 -0
  24. package/lib/bind-support.js +63 -0
  25. package/lib/bind-support.js.map +1 -0
  26. package/lib/binding-store.d.ts +104 -0
  27. package/lib/binding-store.d.ts.map +1 -0
  28. package/lib/binding-store.js +354 -0
  29. package/lib/binding-store.js.map +1 -0
  30. package/lib/bridge.d.ts +248 -0
  31. package/lib/bridge.d.ts.map +1 -0
  32. package/lib/bridge.js +961 -0
  33. package/lib/bridge.js.map +1 -0
  34. package/lib/channel-label.d.ts +46 -0
  35. package/lib/channel-label.d.ts.map +1 -0
  36. package/lib/channel-label.js +89 -0
  37. package/lib/channel-label.js.map +1 -0
  38. package/lib/channel-session-factory.d.ts +76 -0
  39. package/lib/channel-session-factory.d.ts.map +1 -0
  40. package/lib/channel-session-factory.js +187 -0
  41. package/lib/channel-session-factory.js.map +1 -0
  42. package/lib/commands/bind.d.ts +21 -0
  43. package/lib/commands/bind.d.ts.map +1 -0
  44. package/lib/commands/bind.js +91 -0
  45. package/lib/commands/bind.js.map +1 -0
  46. package/lib/commands/help.d.ts +15 -0
  47. package/lib/commands/help.d.ts.map +1 -0
  48. package/lib/commands/help.js +89 -0
  49. package/lib/commands/help.js.map +1 -0
  50. package/lib/commands/index.d.ts +122 -0
  51. package/lib/commands/index.d.ts.map +1 -0
  52. package/lib/commands/index.js +63 -0
  53. package/lib/commands/index.js.map +1 -0
  54. package/lib/commands/locale.d.ts +9 -0
  55. package/lib/commands/locale.d.ts.map +1 -0
  56. package/lib/commands/locale.js +27 -0
  57. package/lib/commands/locale.js.map +1 -0
  58. package/lib/commands/mirror.d.ts +14 -0
  59. package/lib/commands/mirror.d.ts.map +1 -0
  60. package/lib/commands/mirror.js +44 -0
  61. package/lib/commands/mirror.js.map +1 -0
  62. package/lib/commands/model.d.ts +20 -0
  63. package/lib/commands/model.d.ts.map +1 -0
  64. package/lib/commands/model.js +106 -0
  65. package/lib/commands/model.js.map +1 -0
  66. package/lib/commands/models.d.ts +14 -0
  67. package/lib/commands/models.d.ts.map +1 -0
  68. package/lib/commands/models.js +67 -0
  69. package/lib/commands/models.js.map +1 -0
  70. package/lib/commands/new.d.ts +14 -0
  71. package/lib/commands/new.d.ts.map +1 -0
  72. package/lib/commands/new.js +37 -0
  73. package/lib/commands/new.js.map +1 -0
  74. package/lib/commands/status.d.ts +12 -0
  75. package/lib/commands/status.d.ts.map +1 -0
  76. package/lib/commands/status.js +30 -0
  77. package/lib/commands/status.js.map +1 -0
  78. package/lib/commands/stop.d.ts +16 -0
  79. package/lib/commands/stop.d.ts.map +1 -0
  80. package/lib/commands/stop.js +27 -0
  81. package/lib/commands/stop.js.map +1 -0
  82. package/lib/commands/version.d.ts +25 -0
  83. package/lib/commands/version.d.ts.map +1 -0
  84. package/lib/commands/version.js +57 -0
  85. package/lib/commands/version.js.map +1 -0
  86. package/lib/config.d.ts +119 -0
  87. package/lib/config.d.ts.map +1 -0
  88. package/lib/config.js +60 -0
  89. package/lib/config.js.map +1 -0
  90. package/lib/debug-logger.d.ts +8 -0
  91. package/lib/debug-logger.d.ts.map +1 -0
  92. package/lib/debug-logger.js +32 -0
  93. package/lib/debug-logger.js.map +1 -0
  94. package/lib/dsh-home.d.ts +12 -0
  95. package/lib/dsh-home.d.ts.map +1 -0
  96. package/lib/dsh-home.js +31 -0
  97. package/lib/dsh-home.js.map +1 -0
  98. package/lib/failure-display.d.ts +10 -0
  99. package/lib/failure-display.d.ts.map +1 -0
  100. package/lib/failure-display.js +42 -0
  101. package/lib/failure-display.js.map +1 -0
  102. package/lib/file-provider.d.ts +96 -0
  103. package/lib/file-provider.d.ts.map +1 -0
  104. package/lib/file-provider.js +44 -0
  105. package/lib/file-provider.js.map +1 -0
  106. package/lib/index.d.ts +31 -0
  107. package/lib/index.d.ts.map +1 -0
  108. package/lib/index.js +31 -0
  109. package/lib/index.js.map +1 -0
  110. package/lib/interactions/index.d.ts +13 -0
  111. package/lib/interactions/index.d.ts.map +1 -0
  112. package/lib/interactions/index.js +13 -0
  113. package/lib/interactions/index.js.map +1 -0
  114. package/lib/interactions/question-backend.d.ts +133 -0
  115. package/lib/interactions/question-backend.d.ts.map +1 -0
  116. package/lib/interactions/question-backend.js +37 -0
  117. package/lib/interactions/question-backend.js.map +1 -0
  118. package/lib/interactions/question-presenter.d.ts +68 -0
  119. package/lib/interactions/question-presenter.d.ts.map +1 -0
  120. package/lib/interactions/question-presenter.js +425 -0
  121. package/lib/interactions/question-presenter.js.map +1 -0
  122. package/lib/interactions/question-renderer.d.ts +37 -0
  123. package/lib/interactions/question-renderer.d.ts.map +1 -0
  124. package/lib/interactions/question-renderer.js +79 -0
  125. package/lib/interactions/question-renderer.js.map +1 -0
  126. package/lib/interactions/question-state.d.ts +106 -0
  127. package/lib/interactions/question-state.d.ts.map +1 -0
  128. package/lib/interactions/question-state.js +99 -0
  129. package/lib/interactions/question-state.js.map +1 -0
  130. package/lib/interactions/question-text-answer.d.ts +37 -0
  131. package/lib/interactions/question-text-answer.d.ts.map +1 -0
  132. package/lib/interactions/question-text-answer.js +70 -0
  133. package/lib/interactions/question-text-answer.js.map +1 -0
  134. package/lib/interactions/question-waterfall-backend.d.ts +42 -0
  135. package/lib/interactions/question-waterfall-backend.d.ts.map +1 -0
  136. package/lib/interactions/question-waterfall-backend.js +162 -0
  137. package/lib/interactions/question-waterfall-backend.js.map +1 -0
  138. package/lib/lifecycle.d.ts +36 -0
  139. package/lib/lifecycle.d.ts.map +1 -0
  140. package/lib/lifecycle.js +303 -0
  141. package/lib/lifecycle.js.map +1 -0
  142. package/lib/loggable-error.d.ts +10 -0
  143. package/lib/loggable-error.d.ts.map +1 -0
  144. package/lib/loggable-error.js +32 -0
  145. package/lib/loggable-error.js.map +1 -0
  146. package/lib/message-converter.d.ts +64 -0
  147. package/lib/message-converter.d.ts.map +1 -0
  148. package/lib/message-converter.js +191 -0
  149. package/lib/message-converter.js.map +1 -0
  150. package/lib/model-selection.d.ts +54 -0
  151. package/lib/model-selection.d.ts.map +1 -0
  152. package/lib/model-selection.js +116 -0
  153. package/lib/model-selection.js.map +1 -0
  154. package/lib/outbox/binding-resolver.d.ts +23 -0
  155. package/lib/outbox/binding-resolver.d.ts.map +1 -0
  156. package/lib/outbox/binding-resolver.js +38 -0
  157. package/lib/outbox/binding-resolver.js.map +1 -0
  158. package/lib/outbox/capabilities.d.ts +48 -0
  159. package/lib/outbox/capabilities.d.ts.map +1 -0
  160. package/lib/outbox/capabilities.js +35 -0
  161. package/lib/outbox/capabilities.js.map +1 -0
  162. package/lib/outbox/index.d.ts +14 -0
  163. package/lib/outbox/index.d.ts.map +1 -0
  164. package/lib/outbox/index.js +14 -0
  165. package/lib/outbox/index.js.map +1 -0
  166. package/lib/outbox/service.d.ts +48 -0
  167. package/lib/outbox/service.d.ts.map +1 -0
  168. package/lib/outbox/service.js +74 -0
  169. package/lib/outbox/service.js.map +1 -0
  170. package/lib/outbox/target.d.ts +17 -0
  171. package/lib/outbox/target.d.ts.map +1 -0
  172. package/lib/outbox/target.js +15 -0
  173. package/lib/outbox/target.js.map +1 -0
  174. package/lib/outbox/tool-send.d.ts +19 -0
  175. package/lib/outbox/tool-send.d.ts.map +1 -0
  176. package/lib/outbox/tool-send.js +77 -0
  177. package/lib/outbox/tool-send.js.map +1 -0
  178. package/lib/outbox/types.d.ts +42 -0
  179. package/lib/outbox/types.d.ts.map +1 -0
  180. package/lib/outbox/types.js +30 -0
  181. package/lib/outbox/types.js.map +1 -0
  182. package/lib/plugin.d.ts +27 -0
  183. package/lib/plugin.d.ts.map +1 -0
  184. package/lib/plugin.js +47 -0
  185. package/lib/plugin.js.map +1 -0
  186. package/lib/reply-context-store.d.ts +69 -0
  187. package/lib/reply-context-store.d.ts.map +1 -0
  188. package/lib/reply-context-store.js +75 -0
  189. package/lib/reply-context-store.js.map +1 -0
  190. package/lib/reply-router.d.ts +138 -0
  191. package/lib/reply-router.d.ts.map +1 -0
  192. package/lib/reply-router.js +674 -0
  193. package/lib/reply-router.js.map +1 -0
  194. package/lib/session-router.d.ts +49 -0
  195. package/lib/session-router.d.ts.map +1 -0
  196. package/lib/session-router.js +45 -0
  197. package/lib/session-router.js.map +1 -0
  198. package/lib/workspace-resolver.d.ts +67 -0
  199. package/lib/workspace-resolver.d.ts.map +1 -0
  200. package/lib/workspace-resolver.js +102 -0
  201. package/lib/workspace-resolver.js.map +1 -0
  202. package/package.json +103 -0
@@ -0,0 +1,603 @@
1
+ /**
2
+ * AgentManager — the single place that touches `ctx.agents`.
3
+ *
4
+ * Ownership model (doc H0.4/H0.7):
5
+ * - `ctx.agents.get()` returns a live agent the bridge does NOT own — it is
6
+ * never disposed here.
7
+ * - `ctx.agents.create()` / `ctx.agents.resume()` return an `AgentHandle`;
8
+ * the bridge MUST hold every handle it created/resumed and dispose it on
9
+ * plugin unload. Owned handles live in `owned` and are disposed exactly
10
+ * once by `disposeAll()`.
11
+ *
12
+ * Routing is expressed as an `AgentRouteSpec`, never an `agentId` (the
13
+ * Harness Agent identity is the `SessionId`). `create` and `resume` receive
14
+ * the SAME route so provider/model/maxTokens stay identical on both paths
15
+ * (doc H0.5 route parity).
16
+ *
17
+ * Create-vs-resume is decided by the CALLER (the bridge), not by error-regex
18
+ * fallback. Persistence is an OPTIONAL capability resolved LIVE at the use
19
+ * site: `canResume()` tells the caller whether a sessionPersistence service
20
+ * is currently mounted, `exists()` probes membership via the live service,
21
+ * and `probePersisted()` answers the atomic unavailable/present/missing
22
+ * question in one resolver call (no canResume/exists TOCTOU across a
23
+ * persistence HMR) — corruption / unsupported-format / backend failures
24
+ * propagate loudly rather than being misread as "no persistence".
25
+ *
26
+ * Global concurrency gate: at most `maxConcurrency` `create()`/`resume()` calls
27
+ * are in flight at once across all sessions; `get()` (a live lookup) is never
28
+ * limited.
29
+ */
30
+ import { SessionId } from '@deepseek-ai/dsh-session';
31
+ import { agentPresetProjectionDefinition, } from '@deepseek-ai/dsh-agent-preset-registry';
32
+ /** Persistence was configured for the binding, but is unavailable right now. */
33
+ export class PersistenceUnavailableError extends Error {
34
+ sessionId;
35
+ bindingKey;
36
+ constructor(sessionId, bindingKey) {
37
+ super(`persistence is temporarily unavailable for session '${sessionId}'` +
38
+ (bindingKey ? ` (binding '${bindingKey}')` : '') +
39
+ '; refusing to recreate a durable channel session');
40
+ this.sessionId = sessionId;
41
+ this.bindingKey = bindingKey;
42
+ this.name = 'PersistenceUnavailableError';
43
+ }
44
+ }
45
+ /**
46
+ * A durable binding references a persisted session that no longer exists
47
+ * (session-not-found, aligned with the official Host's
48
+ * "persisted identity missing -> session-not-found"). With a
49
+ * sessionPersistence service mounted, a missing persisted session behind an
50
+ * existing binding is a binding/session durability inconsistency — NEVER a
51
+ * first create — so resolution fails loudly instead of silently
52
+ * blank-recreating the same session id. Deployments WITHOUT persistence
53
+ * explicitly ephemeral bindings never throw this: they recreate on the recorded id.
54
+ */
55
+ export class SessionNotFoundError extends Error {
56
+ sessionId;
57
+ bindingKey;
58
+ constructor(sessionId, bindingKey) {
59
+ super(`session '${sessionId}' not found in persistence: the binding` +
60
+ (bindingKey ? ` '${bindingKey}'` : '') +
61
+ ` references a durable session that no longer exists (binding/session ` +
62
+ `durability inconsistency); refusing to silently recreate it. Restore ` +
63
+ `the session or clear/repair the binding.`);
64
+ this.sessionId = sessionId;
65
+ this.bindingKey = bindingKey;
66
+ this.name = 'SessionNotFoundError';
67
+ }
68
+ }
69
+ /** Filter out undefined optional agentOptions fields (route parity helper). */
70
+ export function optionsFor(route) {
71
+ const options = {};
72
+ if (route.provider)
73
+ options.provider = route.provider;
74
+ if (route.model)
75
+ options.model = route.model;
76
+ if (route.maxTokens !== undefined)
77
+ options.maxTokens = route.maxTokens;
78
+ return Object.keys(options).length > 0 ? options : undefined;
79
+ }
80
+ /**
81
+ * Resolve a route's provider/model, falling back to Harness's default model
82
+ * selection when the route leaves the model unset.
83
+ *
84
+ * `{{model}}` (the persona variable that fails with "prompt variable has no
85
+ * value") depends only on `model`, so a route that already pins a model —
86
+ * with or without a provider — is left untouched. Only a missing model is
87
+ * filled from the default (and the default's provider rides along when the
88
+ * route also left provider unset).
89
+ *
90
+ * The default model is read live (per agent creation), so new channel sessions
91
+ * follow the user's Harness-wide default while sessions pinned to an explicit
92
+ * route keep their own provider/model.
93
+ */
94
+ export function resolveRoute(route, defaultSelection) {
95
+ if (route.model)
96
+ return route;
97
+ if (!defaultSelection?.model)
98
+ return route;
99
+ return {
100
+ ...route,
101
+ model: defaultSelection.model,
102
+ provider: route.provider ?? defaultSelection.provider,
103
+ };
104
+ }
105
+ /**
106
+ * Probe a persisted session's existence through the persistence service's
107
+ * `list()` membership. A session that is absent returns `false`; any backend
108
+ * failure (corruption, unsupported format, connectivity) propagates loudly.
109
+ *
110
+ * The persistence service is resolved LIVE on every call (a resolver, not a
111
+ * startup snapshot): a sessionPersistence mounted/unmounted/replaced after
112
+ * the bridge started is observed on the next probe — reversible Cordis
113
+ * lifecycle parity, since `ctx.get` only returns currently active providers.
114
+ */
115
+ export class PersistenceMembershipProbe {
116
+ resolvePersistence;
117
+ constructor(resolvePersistence) {
118
+ this.resolvePersistence = resolvePersistence;
119
+ }
120
+ async exists(sessionId) {
121
+ const persistence = this.resolvePersistence();
122
+ if (!persistence)
123
+ return false;
124
+ const headers = await persistence.list();
125
+ const target = sessionId;
126
+ return headers.some((header) => persistedSessionId(header) === target);
127
+ }
128
+ /** Atomic probe: the live capability is resolved exactly once per call. */
129
+ async probe(sessionId) {
130
+ const persistence = this.resolvePersistence();
131
+ if (!persistence)
132
+ return 'unavailable';
133
+ const headers = await persistence.list();
134
+ return headers.some((header) => persistedSessionId(header) === sessionId) ? 'present' : 'missing';
135
+ }
136
+ }
137
+ /**
138
+ * Session V3 persistence `list()` always returns snapshots. Identity lives in
139
+ * the snapshot header; the bridge intentionally does not retain the removed
140
+ * pre-V3 bare-header compatibility path.
141
+ */
142
+ function persistedSessionId(entry) {
143
+ return String(entry.header.id);
144
+ }
145
+ /**
146
+ * Read one durable V3 session through the public read handle. A channel bridge
147
+ * never depends on an implementation-specific persistence reader.
148
+ */
149
+ export async function resolvePersistedInspection(persistence, sessionId) {
150
+ const handle = await persistence.open(sessionId, 'read');
151
+ try {
152
+ return {
153
+ meta: handle.header,
154
+ events: (await handle.read()).events,
155
+ };
156
+ }
157
+ finally {
158
+ await handle.close();
159
+ }
160
+ }
161
+ /**
162
+ * Reconstruct the preset a persisted session actually runs, from its durable
163
+ * inspection: the creation header's `agentPreset` advanced by every
164
+ * `agent-preset/selected` event via the official
165
+ * `agentPresetProjectionDefinition` fold.
166
+ */
167
+ function resolvePersistedPreset(header, events) {
168
+ let state = agentPresetProjectionDefinition.init(header);
169
+ for (const event of events) {
170
+ state = agentPresetProjectionDefinition.apply(state, event);
171
+ }
172
+ return state ?? undefined;
173
+ }
174
+ /**
175
+ * Real gateway over `ctx.agents`. This is the only Harness import surface in
176
+ * the bridge (besides the `session/event` feed consumed by ReplyRouter).
177
+ *
178
+ * Persistence is an OPTIONAL capability resolved LIVE at the use site: the
179
+ * caller passes a resolver (`() => ctx.get('sessionPersistence')`), so
180
+ * `canResume()` and the existence probe reflect the service's CURRENT
181
+ * presence — mounting, unmounting, or replacing the service after the bridge
182
+ * started is observed on the next probe (never a startup snapshot).
183
+ */
184
+ export class HarnessAgentGateway {
185
+ ctx;
186
+ probe;
187
+ resolvePersistence;
188
+ /**
189
+ * All persisted session ids (shape-tolerant, issue #8) — the `/bind`
190
+ * resolution universe. Empty when no persistence is mounted.
191
+ */
192
+ async listPersistedSessionIds() {
193
+ const persistence = this.resolvePersistence();
194
+ if (!persistence)
195
+ return [];
196
+ const rows = await persistence.list();
197
+ return rows.map((row) => persistedSessionId(row));
198
+ }
199
+ /**
200
+ * The persisted Agent preset of one session (issue #6 route parity): the
201
+ * official `agentPresetProjectionDefinition` fold over the durable
202
+ * inspection. Undefined when no persistence / no recorded preset.
203
+ */
204
+ async persistedPresetOf(sessionId) {
205
+ const persistence = this.resolvePersistence();
206
+ if (!persistence)
207
+ return undefined;
208
+ const inspection = await resolvePersistedInspection(persistence, SessionId(sessionId));
209
+ return inspection ? resolvePersistedPreset(inspection.meta, inspection.events) : undefined;
210
+ }
211
+ constructor(ctx, resolvePersistence) {
212
+ this.ctx = ctx;
213
+ this.resolvePersistence = resolvePersistence ?? (() => undefined);
214
+ this.probe = new PersistenceMembershipProbe(this.resolvePersistence);
215
+ }
216
+ get(sessionId) {
217
+ const agent = this.ctx.agents.get(SessionId(sessionId));
218
+ if (!agent)
219
+ return undefined;
220
+ return {
221
+ id: agent.id,
222
+ agent,
223
+ followup: (message) => agent.followup(message),
224
+ whenIdle: () => agent.whenIdle(),
225
+ };
226
+ }
227
+ canResume() {
228
+ // Only a currently mounted sessionPersistence service enables resume.
229
+ return this.resolvePersistence() !== undefined;
230
+ }
231
+ async exists(sessionId) {
232
+ return this.probe.exists(sessionId);
233
+ }
234
+ async probePersisted(sessionId) {
235
+ return this.probe.probe(sessionId);
236
+ }
237
+ /** Read Harness's live default-model selection (undefined when absent). */
238
+ defaultSelection() {
239
+ const service = this.ctx.get('agentDefaultModel');
240
+ return service?.currentSelection();
241
+ }
242
+ /**
243
+ * Resolve and mount the official Agent preset before publication, matching
244
+ * the Harness Host's create/resume composition boundary. Without this join,
245
+ * preset-scoped tools such as `ask_user_question` are invisible to the Agent.
246
+ */
247
+ async composePreset(presetId, setup) {
248
+ const presets = this.ctx.get('agentPresets');
249
+ // Test/minimal hosts without the optional roster retain the historical
250
+ // metadata behavior; the official runtime always provides this service.
251
+ if (!presets)
252
+ return { agentPreset: presetId, setup };
253
+ const resolvedId = (await presets.resolve(presetId)).id;
254
+ return {
255
+ agentPreset: resolvedId,
256
+ setup: async (agentCtx, agent) => {
257
+ await presets.mount(agentCtx, resolvedId);
258
+ return setup?.(agentCtx, agent);
259
+ },
260
+ };
261
+ }
262
+ async create(sessionId, route, setup, meta) {
263
+ const resolved = resolveRoute(route, this.defaultSelection());
264
+ const composition = await this.composePreset(resolved.preset, setup);
265
+ const handle = await this.ctx.agents.create({
266
+ sessionId: SessionId(sessionId),
267
+ // `{{cwd}}` reads `session.header.cwd`, and `dsh-workspace` groups the
268
+ // session under the workspace whose path matches that cwd. The cwd is
269
+ // decided by the CALLER (the bridge) and passed through `meta.cwd` —
270
+ // `HarnessAgentGateway` only creates the session with the given cwd and
271
+ // never falls back to `process.cwd()`. This must be set at creation —
272
+ // `resume` has no `meta` and cannot add it later.
273
+ meta: {
274
+ ...(meta?.cwd ? { cwd: meta.cwd } : {}),
275
+ ...(composition.agentPreset ? { agentPreset: composition.agentPreset } : {}),
276
+ },
277
+ agentOptions: optionsFor(resolved),
278
+ setup: composition.setup,
279
+ });
280
+ return this.wrap(handle);
281
+ }
282
+ async resume(sessionId, route, setup) {
283
+ // Route parity (doc H0.5): resume uses the SAME optionsFor(resolveRoute(...))
284
+ // as create. NEVER `model ?? agentId`.
285
+ const resolved = resolveRoute(route, this.defaultSelection());
286
+ const persistence = this.resolvePersistence();
287
+ const inspected = persistence
288
+ ? await resolvePersistedInspection(persistence, SessionId(sessionId))
289
+ : undefined;
290
+ const persistedPreset = inspected
291
+ ? resolvePersistedPreset(inspected.meta, inspected.events)
292
+ : undefined;
293
+ if (persistedPreset && resolved.preset && persistedPreset !== resolved.preset) {
294
+ throw new AgentPresetConflictError(sessionId, resolved.preset, persistedPreset);
295
+ }
296
+ // Persisted composition wins. Sessions created before Agent presets were
297
+ // recorded have no value, so they intentionally adopt the current default.
298
+ const composition = await this.composePreset(persistedPreset ?? resolved.preset, setup);
299
+ const handle = await this.ctx.agents.resume({
300
+ resumeSessionId: SessionId(sessionId),
301
+ agentOptions: optionsFor(resolved),
302
+ setup: composition.setup,
303
+ });
304
+ return this.wrap(handle);
305
+ }
306
+ wrap(handle) {
307
+ return {
308
+ id: handle.agent.id,
309
+ agent: handle.agent,
310
+ followup: (message) => handle.agent.followup(message),
311
+ whenIdle: () => handle.agent.whenIdle(),
312
+ dispose: () => handle.dispose(),
313
+ };
314
+ }
315
+ }
316
+ export class AgentManager {
317
+ gateway;
318
+ logger;
319
+ inFlight = new Map();
320
+ /** Handles this manager created/resumed — the ones it must dispose. */
321
+ owned = new Map();
322
+ /** Resolved refs, kept for drain (`whenIdle`) lookups. */
323
+ refs = new Map();
324
+ /** Agents that already received the one-time channel-command setup. */
325
+ configuredAgents = new WeakSet();
326
+ /** sessionId -> binding, the reverse lookup used by the ReplyRouter. */
327
+ bindings = new Map();
328
+ maxConcurrency;
329
+ active = 0;
330
+ /** Waiters queued for a free concurrency slot. */
331
+ waiters = [];
332
+ closed = false;
333
+ constructor(gateway, logger, maxConcurrency = 4) {
334
+ this.gateway = gateway;
335
+ this.logger = logger;
336
+ this.maxConcurrency = Math.max(1, maxConcurrency);
337
+ }
338
+ /** Whether a sessionPersistence service enables `resume`. */
339
+ canResume() {
340
+ return this.gateway.canResume();
341
+ }
342
+ /** Probe whether a persisted session exists. Backend failures propagate. */
343
+ exists(sessionId) {
344
+ return this.gateway.exists(sessionId);
345
+ }
346
+ /**
347
+ * Atomic persistence probe: resolves the LIVE capability once and answers
348
+ * `unavailable` / `present` / `missing` — the bridge's single decision
349
+ * point for recreate-vs-resume-vs-fail, immune to a persistence HMR between
350
+ * `canResume()` and `exists()`.
351
+ */
352
+ async probePersisted(sessionId) {
353
+ if (this.gateway.probePersisted)
354
+ return this.gateway.probePersisted(sessionId);
355
+ // Fallback for minimal test gateways without the atomic probe: two live
356
+ // lookups (deterministic in tests).
357
+ if (!this.gateway.canResume())
358
+ return 'unavailable';
359
+ return (await this.gateway.exists(sessionId)) ? 'present' : 'missing';
360
+ }
361
+ /**
362
+ * Create a NEW agent for a session (no prior binding). Calls
363
+ * `gateway.create` directly (under the concurrency slot), owns the handle,
364
+ * and returns the ref. Never resumes — the caller already decided this is a
365
+ * fresh conversation. Single-flight per session id.
366
+ */
367
+ create(sessionId, route, setup, meta) {
368
+ if (this.closed) {
369
+ return Promise.reject(new Error(`AgentManager is closed; cannot create '${sessionId}'`));
370
+ }
371
+ const pending = this.inFlight.get(sessionId);
372
+ if (pending)
373
+ return pending;
374
+ const run = this.doCreate(sessionId, route, setup, meta);
375
+ this.inFlight.set(sessionId, run);
376
+ void run.then(() => {
377
+ this.inFlight.delete(sessionId);
378
+ }, () => {
379
+ this.inFlight.delete(sessionId);
380
+ });
381
+ return run;
382
+ }
383
+ /**
384
+ * Resolve an agent for an EXISTING, persisted session: live `get` first; on
385
+ * a miss, `gateway.resume(route)`. A resume failure propagates loudly
386
+ * (throws) — never falls back to create and never sniffs error messages.
387
+ * Single-flight per session id.
388
+ */
389
+ resolve(sessionId, route, setup) {
390
+ if (this.closed) {
391
+ return Promise.reject(new Error(`AgentManager is closed; cannot resolve '${sessionId}'`));
392
+ }
393
+ const pending = this.inFlight.get(sessionId);
394
+ if (pending)
395
+ return pending;
396
+ const run = this.doResolve(sessionId, route, setup);
397
+ this.inFlight.set(sessionId, run);
398
+ void run.then(() => {
399
+ this.inFlight.delete(sessionId);
400
+ }, () => {
401
+ this.inFlight.delete(sessionId);
402
+ });
403
+ return run;
404
+ }
405
+ /**
406
+ * Borrow the LIVE agent for a session, when one is loaded in this process.
407
+ * Returns `undefined` when there is no live agent — the caller (the Session
408
+ * factory, for channel-session lifecycle decisions) decides what to do next
409
+ * (resume, or a cwd/workspace-aware recreate). Never creates or resumes and
410
+ * never takes ownership (the borrowed agent is never disposed here). Runs
411
+ * the one-time setup against a borrowed agent, exactly once.
412
+ */
413
+ borrowIfLive(sessionId, route, setup) {
414
+ if (this.closed) {
415
+ return Promise.reject(new Error(`AgentManager is closed; cannot borrow '${sessionId}'`));
416
+ }
417
+ return this.doBorrowIfLive(sessionId, route, setup);
418
+ }
419
+ /** Register the binding associated with a session (reverse reply routing). */
420
+ registerBinding(binding) {
421
+ this.bindings.set(binding.sessionId, binding);
422
+ }
423
+ /** Reverse lookup for the ReplyRouter. */
424
+ bindingFor(sessionId) {
425
+ return this.bindings.get(sessionId);
426
+ }
427
+ /**
428
+ * Live agent lookup for the /stop fast path (spec §8). Returns the raw
429
+ * Agent when it is currently live in this process — NEVER creates or
430
+ * resumes a session just to answer this probe.
431
+ */
432
+ getLiveAgent(sessionId) {
433
+ return this.gateway.get(sessionId)?.agent;
434
+ }
435
+ /** Resolved ref for drain purposes, if any. */
436
+ refFor(sessionId) {
437
+ return this.refs.get(sessionId);
438
+ }
439
+ /** Session ids that currently have an active turn (for drain). */
440
+ activeSessions() {
441
+ return [...this.bindings.keys()];
442
+ }
443
+ /**
444
+ * Dispose every owned handle exactly once and clear all tracking. Agents
445
+ * obtained via `gateway.get()` (not owned) are never disposed.
446
+ */
447
+ async disposeAll() {
448
+ this.closed = true;
449
+ const waiters = this.waiters.splice(0);
450
+ for (const wake of waiters)
451
+ wake();
452
+ const handles = [...this.owned.values()];
453
+ this.owned.clear();
454
+ this.refs.clear();
455
+ this.bindings.clear();
456
+ const results = await Promise.allSettled(handles.map((handle) => handle.dispose()));
457
+ for (const result of results) {
458
+ if (result.status === 'rejected') {
459
+ this.logger.error(`failed to dispose an owned agent handle`, result.reason);
460
+ }
461
+ }
462
+ }
463
+ /**
464
+ * Dispose a single owned handle (used to roll back a create whose binding
465
+ * write failed afterward). No-op for handles the manager does not own.
466
+ */
467
+ async disposeSession(sessionId) {
468
+ const handle = this.owned.get(sessionId);
469
+ if (!handle)
470
+ return;
471
+ this.owned.delete(sessionId);
472
+ this.refs.delete(sessionId);
473
+ this.bindings.delete(sessionId);
474
+ try {
475
+ await handle.dispose();
476
+ }
477
+ catch (error) {
478
+ this.logger.error(`failed to dispose owned agent handle for '${sessionId}'`, error);
479
+ }
480
+ }
481
+ /**
482
+ * Retire a session's reference and reverse binding and dispose it ONLY if the
483
+ * manager owns the handle. Borrowed / unknown agents are released
484
+ * from local tracking but NEVER disposed. Retiring never touches persisted
485
+ * history — the old session keeps its durable log.
486
+ */
487
+ async retireSession(sessionId) {
488
+ this.refs.delete(sessionId);
489
+ this.bindings.delete(sessionId);
490
+ const handle = this.owned.get(sessionId);
491
+ if (!handle)
492
+ return;
493
+ this.owned.delete(sessionId);
494
+ try {
495
+ await handle.dispose();
496
+ }
497
+ catch (error) {
498
+ this.logger.error(`failed to dispose owned agent handle for '${sessionId}'`, error);
499
+ }
500
+ }
501
+ /**
502
+ * One-time channel-command setup for a BORROWED live agent. A
503
+ * borrowed agent never went through create/resume, so its setup could not
504
+ * have run at publication; run it here exactly once against the agent's
505
+ * scoped context. Setup failure propagates to the caller. The borrowed
506
+ * agent is never disposed here.
507
+ */
508
+ async ensureBorrowedSetup(agent, setup) {
509
+ if (!setup)
510
+ return;
511
+ if (this.configuredAgents.has(agent.agent))
512
+ return;
513
+ const commit = await setup(agent.agent.ctx, agent.agent);
514
+ commit?.commit();
515
+ this.configuredAgents.add(agent.agent);
516
+ }
517
+ async doCreate(sessionId, route, setup, meta) {
518
+ return this.withSlot(async () => {
519
+ const handle = await this.gateway.create(sessionId, route, setup, meta);
520
+ this.owned.set(sessionId, handle);
521
+ if (setup)
522
+ this.configuredAgents.add(handle.agent);
523
+ return this.makeRef(sessionId, route, handle);
524
+ });
525
+ }
526
+ async doResolve(sessionId, route, setup) {
527
+ const live = this.gateway.get(sessionId);
528
+ if (live) {
529
+ await this.ensureBorrowedSetup(live, setup);
530
+ return this.makeRef(sessionId, route, live);
531
+ }
532
+ return this.withSlot(async () => {
533
+ const handle = await this.gateway.resume(sessionId, route, setup);
534
+ this.owned.set(sessionId, handle);
535
+ if (setup)
536
+ this.configuredAgents.add(handle.agent);
537
+ return this.makeRef(sessionId, route, handle);
538
+ });
539
+ }
540
+ async doBorrowIfLive(sessionId, route, setup) {
541
+ const live = this.gateway.get(sessionId);
542
+ if (!live)
543
+ return undefined;
544
+ await this.ensureBorrowedSetup(live, setup);
545
+ return this.makeRef(sessionId, route, live);
546
+ }
547
+ async withSlot(fn) {
548
+ await this.acquireSlot();
549
+ try {
550
+ return await fn();
551
+ }
552
+ finally {
553
+ this.releaseSlot();
554
+ }
555
+ }
556
+ async acquireSlot() {
557
+ while (true) {
558
+ if (this.closed) {
559
+ throw new Error(`AgentManager is closed; cannot resolve a session`);
560
+ }
561
+ if (this.active < this.maxConcurrency) {
562
+ this.active += 1;
563
+ return;
564
+ }
565
+ await new Promise((resolve) => this.waiters.push(resolve));
566
+ }
567
+ }
568
+ releaseSlot() {
569
+ this.active -= 1;
570
+ const next = this.waiters.shift();
571
+ if (next)
572
+ next();
573
+ }
574
+ makeRef(sessionId, route, agent) {
575
+ const ref = {
576
+ sessionId,
577
+ route,
578
+ agent: agent.agent,
579
+ followup: (message) => agent.followup(message),
580
+ whenIdle: () => agent.whenIdle(),
581
+ release: () => {
582
+ // Simple ownership: release is a marker; actual disposal happens once
583
+ // in disposeAll() for handles this manager owns.
584
+ },
585
+ };
586
+ this.refs.set(sessionId, ref);
587
+ return ref;
588
+ }
589
+ }
590
+ /** A durable session cannot be silently recomposed under a different preset. */
591
+ export class AgentPresetConflictError extends Error {
592
+ sessionId;
593
+ requested;
594
+ persisted;
595
+ constructor(sessionId, requested, persisted) {
596
+ super(`session '${sessionId}' uses Agent preset '${persisted}', but route requested '${requested}'`);
597
+ this.sessionId = sessionId;
598
+ this.requested = requested;
599
+ this.persisted = persisted;
600
+ this.name = 'AgentPresetConflictError';
601
+ }
602
+ }
603
+ //# sourceMappingURL=agent-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-manager.js","sourceRoot":"","sources":["../src/agent-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Agent routing (doc H0.1/H0.2 / §30): turn a channel conversation into an
3
+ * `AgentRouteSpec` — a routing snapshot, NOT an identity.
4
+ *
5
+ * Harness Agent identity is the `SessionId` (shared between the agent and its
6
+ * session), so there is no runtime `agentId` parallel to it. A route only
7
+ * describes how to drive the session's agent: an optional Harness preset
8
+ * (`meta.agentPreset`) and/or provider/model/maxTokens (`agentOptions`).
9
+ *
10
+ * Resolution priority: routing override (conversation > account > channel) >
11
+ * `config.agent.default`.
12
+ */
13
+ import type { Config } from './config.js';
14
+ /** How a session's agent should be driven. Never an identity. */
15
+ export interface AgentRouteSpec {
16
+ /** Harness Agent preset, composed into the session's world — NOT identity. */
17
+ preset?: string;
18
+ /** Optional provider route. */
19
+ provider?: string;
20
+ /** Optional model id interpreted by the provider adapter. */
21
+ model?: string;
22
+ /** Optional max output tokens per request. */
23
+ maxTokens?: number;
24
+ }
25
+ export interface AgentRouteInput {
26
+ channelId: string;
27
+ accountId: string;
28
+ conversationId: string;
29
+ }
30
+ /** Compare two routes structurally (used to detect binding route drift). */
31
+ export declare function routesEqual(a: AgentRouteSpec | undefined, b: AgentRouteSpec | undefined): boolean;
32
+ export declare class AgentRouter {
33
+ private readonly config;
34
+ constructor(config: Config);
35
+ resolve(input: AgentRouteInput): AgentRouteSpec;
36
+ }
37
+ //# sourceMappingURL=agent-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-router.d.ts","sourceRoot":"","sources":["../src/agent-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,iEAAiE;AACjE,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,CAAC,EAAE,cAAc,GAAG,SAAS,EAAE,CAAC,EAAE,cAAc,GAAG,SAAS,GAAG,OAAO,CASjG;AAED,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;IAE3C,OAAO,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc;CAYhD"}