@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.
- package/README.md +110 -0
- package/lib/access/controller.d.ts +37 -0
- package/lib/access/controller.d.ts.map +1 -0
- package/lib/access/controller.js +51 -0
- package/lib/access/controller.js.map +1 -0
- package/lib/access/decision.d.ts +18 -0
- package/lib/access/decision.d.ts.map +1 -0
- package/lib/access/decision.js +2 -0
- package/lib/access/decision.js.map +1 -0
- package/lib/access/resolver.d.ts +41 -0
- package/lib/access/resolver.d.ts.map +1 -0
- package/lib/access/resolver.js +31 -0
- package/lib/access/resolver.js.map +1 -0
- package/lib/agent-manager.d.ts +314 -0
- package/lib/agent-manager.d.ts.map +1 -0
- package/lib/agent-manager.js +603 -0
- package/lib/agent-manager.js.map +1 -0
- package/lib/agent-router.d.ts +37 -0
- package/lib/agent-router.d.ts.map +1 -0
- package/lib/agent-router.js +33 -0
- package/lib/agent-router.js.map +1 -0
- package/lib/bind-support.d.ts +23 -0
- package/lib/bind-support.d.ts.map +1 -0
- package/lib/bind-support.js +63 -0
- package/lib/bind-support.js.map +1 -0
- package/lib/binding-store.d.ts +104 -0
- package/lib/binding-store.d.ts.map +1 -0
- package/lib/binding-store.js +354 -0
- package/lib/binding-store.js.map +1 -0
- package/lib/bridge.d.ts +248 -0
- package/lib/bridge.d.ts.map +1 -0
- package/lib/bridge.js +961 -0
- package/lib/bridge.js.map +1 -0
- package/lib/channel-label.d.ts +46 -0
- package/lib/channel-label.d.ts.map +1 -0
- package/lib/channel-label.js +89 -0
- package/lib/channel-label.js.map +1 -0
- package/lib/channel-session-factory.d.ts +76 -0
- package/lib/channel-session-factory.d.ts.map +1 -0
- package/lib/channel-session-factory.js +187 -0
- package/lib/channel-session-factory.js.map +1 -0
- package/lib/commands/bind.d.ts +21 -0
- package/lib/commands/bind.d.ts.map +1 -0
- package/lib/commands/bind.js +91 -0
- package/lib/commands/bind.js.map +1 -0
- package/lib/commands/help.d.ts +15 -0
- package/lib/commands/help.d.ts.map +1 -0
- package/lib/commands/help.js +89 -0
- package/lib/commands/help.js.map +1 -0
- package/lib/commands/index.d.ts +122 -0
- package/lib/commands/index.d.ts.map +1 -0
- package/lib/commands/index.js +63 -0
- package/lib/commands/index.js.map +1 -0
- package/lib/commands/locale.d.ts +9 -0
- package/lib/commands/locale.d.ts.map +1 -0
- package/lib/commands/locale.js +27 -0
- package/lib/commands/locale.js.map +1 -0
- package/lib/commands/mirror.d.ts +14 -0
- package/lib/commands/mirror.d.ts.map +1 -0
- package/lib/commands/mirror.js +44 -0
- package/lib/commands/mirror.js.map +1 -0
- package/lib/commands/model.d.ts +20 -0
- package/lib/commands/model.d.ts.map +1 -0
- package/lib/commands/model.js +106 -0
- package/lib/commands/model.js.map +1 -0
- package/lib/commands/models.d.ts +14 -0
- package/lib/commands/models.d.ts.map +1 -0
- package/lib/commands/models.js +67 -0
- package/lib/commands/models.js.map +1 -0
- package/lib/commands/new.d.ts +14 -0
- package/lib/commands/new.d.ts.map +1 -0
- package/lib/commands/new.js +37 -0
- package/lib/commands/new.js.map +1 -0
- package/lib/commands/status.d.ts +12 -0
- package/lib/commands/status.d.ts.map +1 -0
- package/lib/commands/status.js +30 -0
- package/lib/commands/status.js.map +1 -0
- package/lib/commands/stop.d.ts +16 -0
- package/lib/commands/stop.d.ts.map +1 -0
- package/lib/commands/stop.js +27 -0
- package/lib/commands/stop.js.map +1 -0
- package/lib/commands/version.d.ts +25 -0
- package/lib/commands/version.d.ts.map +1 -0
- package/lib/commands/version.js +57 -0
- package/lib/commands/version.js.map +1 -0
- package/lib/config.d.ts +119 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +60 -0
- package/lib/config.js.map +1 -0
- package/lib/debug-logger.d.ts +8 -0
- package/lib/debug-logger.d.ts.map +1 -0
- package/lib/debug-logger.js +32 -0
- package/lib/debug-logger.js.map +1 -0
- package/lib/dsh-home.d.ts +12 -0
- package/lib/dsh-home.d.ts.map +1 -0
- package/lib/dsh-home.js +31 -0
- package/lib/dsh-home.js.map +1 -0
- package/lib/failure-display.d.ts +10 -0
- package/lib/failure-display.d.ts.map +1 -0
- package/lib/failure-display.js +42 -0
- package/lib/failure-display.js.map +1 -0
- package/lib/file-provider.d.ts +96 -0
- package/lib/file-provider.d.ts.map +1 -0
- package/lib/file-provider.js +44 -0
- package/lib/file-provider.js.map +1 -0
- package/lib/index.d.ts +31 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +31 -0
- package/lib/index.js.map +1 -0
- package/lib/interactions/index.d.ts +13 -0
- package/lib/interactions/index.d.ts.map +1 -0
- package/lib/interactions/index.js +13 -0
- package/lib/interactions/index.js.map +1 -0
- package/lib/interactions/question-backend.d.ts +133 -0
- package/lib/interactions/question-backend.d.ts.map +1 -0
- package/lib/interactions/question-backend.js +37 -0
- package/lib/interactions/question-backend.js.map +1 -0
- package/lib/interactions/question-presenter.d.ts +68 -0
- package/lib/interactions/question-presenter.d.ts.map +1 -0
- package/lib/interactions/question-presenter.js +425 -0
- package/lib/interactions/question-presenter.js.map +1 -0
- package/lib/interactions/question-renderer.d.ts +37 -0
- package/lib/interactions/question-renderer.d.ts.map +1 -0
- package/lib/interactions/question-renderer.js +79 -0
- package/lib/interactions/question-renderer.js.map +1 -0
- package/lib/interactions/question-state.d.ts +106 -0
- package/lib/interactions/question-state.d.ts.map +1 -0
- package/lib/interactions/question-state.js +99 -0
- package/lib/interactions/question-state.js.map +1 -0
- package/lib/interactions/question-text-answer.d.ts +37 -0
- package/lib/interactions/question-text-answer.d.ts.map +1 -0
- package/lib/interactions/question-text-answer.js +70 -0
- package/lib/interactions/question-text-answer.js.map +1 -0
- package/lib/interactions/question-waterfall-backend.d.ts +42 -0
- package/lib/interactions/question-waterfall-backend.d.ts.map +1 -0
- package/lib/interactions/question-waterfall-backend.js +162 -0
- package/lib/interactions/question-waterfall-backend.js.map +1 -0
- package/lib/lifecycle.d.ts +36 -0
- package/lib/lifecycle.d.ts.map +1 -0
- package/lib/lifecycle.js +303 -0
- package/lib/lifecycle.js.map +1 -0
- package/lib/loggable-error.d.ts +10 -0
- package/lib/loggable-error.d.ts.map +1 -0
- package/lib/loggable-error.js +32 -0
- package/lib/loggable-error.js.map +1 -0
- package/lib/message-converter.d.ts +64 -0
- package/lib/message-converter.d.ts.map +1 -0
- package/lib/message-converter.js +191 -0
- package/lib/message-converter.js.map +1 -0
- package/lib/model-selection.d.ts +54 -0
- package/lib/model-selection.d.ts.map +1 -0
- package/lib/model-selection.js +116 -0
- package/lib/model-selection.js.map +1 -0
- package/lib/outbox/binding-resolver.d.ts +23 -0
- package/lib/outbox/binding-resolver.d.ts.map +1 -0
- package/lib/outbox/binding-resolver.js +38 -0
- package/lib/outbox/binding-resolver.js.map +1 -0
- package/lib/outbox/capabilities.d.ts +48 -0
- package/lib/outbox/capabilities.d.ts.map +1 -0
- package/lib/outbox/capabilities.js +35 -0
- package/lib/outbox/capabilities.js.map +1 -0
- package/lib/outbox/index.d.ts +14 -0
- package/lib/outbox/index.d.ts.map +1 -0
- package/lib/outbox/index.js +14 -0
- package/lib/outbox/index.js.map +1 -0
- package/lib/outbox/service.d.ts +48 -0
- package/lib/outbox/service.d.ts.map +1 -0
- package/lib/outbox/service.js +74 -0
- package/lib/outbox/service.js.map +1 -0
- package/lib/outbox/target.d.ts +17 -0
- package/lib/outbox/target.d.ts.map +1 -0
- package/lib/outbox/target.js +15 -0
- package/lib/outbox/target.js.map +1 -0
- package/lib/outbox/tool-send.d.ts +19 -0
- package/lib/outbox/tool-send.d.ts.map +1 -0
- package/lib/outbox/tool-send.js +77 -0
- package/lib/outbox/tool-send.js.map +1 -0
- package/lib/outbox/types.d.ts +42 -0
- package/lib/outbox/types.d.ts.map +1 -0
- package/lib/outbox/types.js +30 -0
- package/lib/outbox/types.js.map +1 -0
- package/lib/plugin.d.ts +27 -0
- package/lib/plugin.d.ts.map +1 -0
- package/lib/plugin.js +47 -0
- package/lib/plugin.js.map +1 -0
- package/lib/reply-context-store.d.ts +69 -0
- package/lib/reply-context-store.d.ts.map +1 -0
- package/lib/reply-context-store.js +75 -0
- package/lib/reply-context-store.js.map +1 -0
- package/lib/reply-router.d.ts +138 -0
- package/lib/reply-router.d.ts.map +1 -0
- package/lib/reply-router.js +674 -0
- package/lib/reply-router.js.map +1 -0
- package/lib/session-router.d.ts +49 -0
- package/lib/session-router.d.ts.map +1 -0
- package/lib/session-router.js +45 -0
- package/lib/session-router.js.map +1 -0
- package/lib/workspace-resolver.d.ts +67 -0
- package/lib/workspace-resolver.d.ts.map +1 -0
- package/lib/workspace-resolver.js +102 -0
- package/lib/workspace-resolver.js.map +1 -0
- 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"}
|