@jini-ai/daemon 0.2.1 → 0.3.1
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 +92 -0
- package/dist/agent-executor.d.ts +864 -42
- package/dist/agent-executor.d.ts.map +1 -1
- package/dist/agent-executor.js +1672 -351
- package/dist/agent-executor.js.map +1 -1
- package/dist/continuation/index.d.ts +1 -0
- package/dist/continuation/index.d.ts.map +1 -1
- package/dist/continuation/index.js +1 -0
- package/dist/continuation/index.js.map +1 -1
- package/dist/continuation/run-scoped-context-store.d.ts +79 -0
- package/dist/continuation/run-scoped-context-store.d.ts.map +1 -0
- package/dist/continuation/run-scoped-context-store.js +56 -0
- package/dist/continuation/run-scoped-context-store.js.map +1 -0
- package/dist/continuation/run-start-handler.d.ts +39 -9
- package/dist/continuation/run-start-handler.d.ts.map +1 -1
- package/dist/continuation/run-start-handler.js +12 -2
- package/dist/continuation/run-start-handler.js.map +1 -1
- package/dist/delegated-tool-bridge.d.ts +8 -0
- package/dist/delegated-tool-bridge.d.ts.map +1 -1
- package/dist/delegated-tool-bridge.js +117 -1
- package/dist/delegated-tool-bridge.js.map +1 -1
- package/dist/event-log.d.ts +18 -105
- package/dist/event-log.d.ts.map +1 -1
- package/dist/event-log.js +0 -17
- package/dist/event-log.js.map +1 -1
- package/dist/frontend-capability-tools.d.ts +1 -1
- package/dist/frontend-capability-tools.js +1 -1
- package/dist/frontend-session-registry.d.ts.map +1 -1
- package/dist/frontend-session-registry.js +26 -10
- package/dist/frontend-session-registry.js.map +1 -1
- package/dist/image-prompt-delivery.d.ts +56 -0
- package/dist/image-prompt-delivery.d.ts.map +1 -0
- package/dist/image-prompt-delivery.js +104 -0
- package/dist/image-prompt-delivery.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/remote-tool-bridge.d.ts +45 -0
- package/dist/remote-tool-bridge.d.ts.map +1 -0
- package/dist/remote-tool-bridge.js +23 -0
- package/dist/remote-tool-bridge.js.map +1 -0
- package/dist/routines/routine-store.js +1 -1
- package/dist/routines/schedule.d.ts +0 -8
- package/dist/routines/schedule.d.ts.map +1 -1
- package/dist/routines/schedule.js +71 -44
- package/dist/routines/schedule.js.map +1 -1
- package/dist/routines/scheduler.d.ts +43 -0
- package/dist/routines/scheduler.d.ts.map +1 -1
- package/dist/routines/scheduler.js +160 -120
- package/dist/routines/scheduler.js.map +1 -1
- package/dist/run/core/retry.d.ts.map +1 -1
- package/dist/run/core/retry.js +47 -35
- package/dist/run/core/retry.js.map +1 -1
- package/dist/run/diagnostics/diagnostics.d.ts.map +1 -1
- package/dist/run/diagnostics/diagnostics.js +149 -91
- package/dist/run/diagnostics/diagnostics.js.map +1 -1
- package/dist/run-lifecycle.d.ts +84 -4
- package/dist/run-lifecycle.d.ts.map +1 -1
- package/dist/run-lifecycle.js +378 -116
- package/dist/run-lifecycle.js.map +1 -1
- package/dist/terminal-session.d.ts +1 -1
- package/dist/terminal-session.d.ts.map +1 -1
- package/dist/terminal-session.js +1 -1
- package/dist/tool-executor.d.ts +26 -6
- package/dist/tool-executor.d.ts.map +1 -1
- package/dist/tool-executor.js +220 -55
- package/dist/tool-executor.js.map +1 -1
- package/dist/tool-result-media.d.ts +79 -0
- package/dist/tool-result-media.d.ts.map +1 -0
- package/dist/tool-result-media.js +80 -0
- package/dist/tool-result-media.js.map +1 -0
- package/dist/tool-result-surfaces.d.ts +78 -0
- package/dist/tool-result-surfaces.d.ts.map +1 -0
- package/dist/tool-result-surfaces.js +92 -0
- package/dist/tool-result-surfaces.js.map +1 -0
- package/package.json +18 -9
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
import { extractResultMedia } from './tool-result-media.js';
|
|
2
|
+
import { splitToolResultSurfaces } from './tool-result-surfaces.js';
|
|
3
|
+
/**
|
|
4
|
+
* Run-protocol `type` for a human-only surface withheld from a tool result.
|
|
5
|
+
*
|
|
6
|
+
* Named for the ext-event a chat host renders it through (`@jini-ai/chat`'s
|
|
7
|
+
* `MCP_UI_EXT_EVENT_NAME`), so a host that already registered
|
|
8
|
+
* `registerMcpUiSurfaceRenderer()` picks these up with no further wiring.
|
|
9
|
+
*/
|
|
10
|
+
export const MCP_UI_EVENT_TYPE = 'mcp-ui';
|
|
11
|
+
/**
|
|
12
|
+
* Channels whose run-event payload declares a `toolUseId`, and therefore want the bridge to supply
|
|
13
|
+
* it.
|
|
14
|
+
*
|
|
15
|
+
* Correlation genuinely differs per channel rather than being universal, so injecting `toolUseId`
|
|
16
|
+
* everywhere would put a field on the wire that the channel's own schema does not declare. The other
|
|
17
|
+
* channels carry their own handle instead — A2UI correlates by `surfaceId`, and so does the
|
|
18
|
+
* protocol's `surface_request`/`surface_response` pair — and a handler driving those sets it from
|
|
19
|
+
* the exchange it opened, which is a strictly better correlation than `toolUseId` anyway: it
|
|
20
|
+
* survives across the several messages one exchange sends.
|
|
21
|
+
*
|
|
22
|
+
* A one-line addition is all a new `toolUseId`-carrying channel needs. Kept explicit rather than
|
|
23
|
+
* inferred so that decision stays visible.
|
|
24
|
+
*/
|
|
25
|
+
const CHANNELS_CARRYING_TOOL_USE_ID = new Set([MCP_UI_EVENT_TYPE]);
|
|
26
|
+
function correlationFor(channel, toolUseId) {
|
|
27
|
+
return CHANNELS_CARRYING_TOOL_USE_ID.has(channel) ? { toolUseId } : {};
|
|
28
|
+
}
|
|
1
29
|
function errorMessage(error) {
|
|
2
30
|
return error instanceof Error ? error.message : String(error);
|
|
3
31
|
}
|
|
@@ -60,9 +88,95 @@ export function createDelegatedToolBridge(options) {
|
|
|
60
88
|
invocation.signal.addEventListener('abort', abortFromTransport, { once: true });
|
|
61
89
|
}
|
|
62
90
|
const run = { id: runId };
|
|
91
|
+
/**
|
|
92
|
+
* The seam a handler needs in order to show something it then WAITS on.
|
|
93
|
+
*
|
|
94
|
+
* Surfaces normally ride out in the return value and are split out below — which is useless to a
|
|
95
|
+
* handler that cannot return until the human has answered the very thing it wants to display.
|
|
96
|
+
* Emitting through here reaches the same run event stream, so a message pushed mid-call is
|
|
97
|
+
* indistinguishable to a renderer from one carried by the result.
|
|
98
|
+
*
|
|
99
|
+
* **Channel-neutral by construction.** The handler names its own channel, and this only injects
|
|
100
|
+
* correlation. That is what lets one seam drive `mcp-ui`, A2UI's multi-turn envelope
|
|
101
|
+
* (`createSurface` → `updateComponents` → …), the protocol's own `surface_request`/
|
|
102
|
+
* `surface_response` pair, or a channel invented later — none of which this file needs to know
|
|
103
|
+
* the shape of, matching `@jini-ai/protocol`'s own posture of typing each channel's body
|
|
104
|
+
* `unknown` and validating where the concrete type is known.
|
|
105
|
+
*
|
|
106
|
+
* Callable any number of times before the call settles; refused after. A handler that stashed
|
|
107
|
+
* this emitter could otherwise paint a surface onto a run whose `tool_result` is already on
|
|
108
|
+
* screen, with no call left to answer it.
|
|
109
|
+
*/
|
|
110
|
+
let settled = false;
|
|
111
|
+
const emitSurface = async (emission) => {
|
|
112
|
+
if (settled)
|
|
113
|
+
throw new Error(`emitSurface: tool call ${toolUseId} has already completed`);
|
|
114
|
+
// Cast because `RunAgentPayload` is a closed union and `channel` is deliberately an open
|
|
115
|
+
// string — a seam that only accepts channels this file already knows about is not a
|
|
116
|
+
// channel-neutral seam. This mirrors `@jini-ai/protocol`'s own posture of typing each
|
|
117
|
+
// channel's BODY `unknown` and validating where the concrete type is known, applied one level
|
|
118
|
+
// up to the channel name itself.
|
|
119
|
+
//
|
|
120
|
+
// Blast radius of a bogus channel is bounded and worth stating: this path is human-only, so
|
|
121
|
+
// the failure mode is an event no renderer subscribes to — nothing rendered. It cannot put
|
|
122
|
+
// anything into model context, which is the property that would actually matter.
|
|
123
|
+
//
|
|
124
|
+
// That bound holds only for an UNKNOWN channel, which is why the spread order below matters.
|
|
125
|
+
// `payload` used to be spread LAST, so a handler could set `type` to a channel this bridge
|
|
126
|
+
// does know — `tool_result`, `mcp-ui` — and set `toolUseId` to a DIFFERENT call's, producing
|
|
127
|
+
// a well-formed forged event correlated against someone else's tool call. The cast is what
|
|
128
|
+
// let it past the closed `RunAgentPayload` union unnoticed. `SurfaceEmission.payload` is
|
|
129
|
+
// documented as "the channel's own fields, merged into the emitted event BESIDE `type`" —
|
|
130
|
+
// beside, not over — so both reserved keys are stripped rather than merely out-ordered.
|
|
131
|
+
// Stripping, not reordering: `correlationFor` returns `{}` for a channel that carries no
|
|
132
|
+
// `toolUseId`, so spread order alone would still let a payload smuggle one onto those.
|
|
133
|
+
const safePayload = { ...emission.payload };
|
|
134
|
+
delete safePayload['type'];
|
|
135
|
+
delete safePayload['toolUseId'];
|
|
136
|
+
const data = {
|
|
137
|
+
...safePayload,
|
|
138
|
+
type: emission.channel,
|
|
139
|
+
...correlationFor(emission.channel, toolUseId),
|
|
140
|
+
};
|
|
141
|
+
await lifecycle.emit(runId, { event: 'agent', data });
|
|
142
|
+
};
|
|
63
143
|
try {
|
|
64
144
|
try {
|
|
65
|
-
const
|
|
145
|
+
const executed = await toolExecutor.execute(principal, run, toolId, input, controller.signal, emitSurface);
|
|
146
|
+
settled = true;
|
|
147
|
+
// Recognized media blocks (images) are collected here purely to populate the sibling
|
|
148
|
+
// `media` field the `tool_result` event carries below, for a UI that wants to render one
|
|
149
|
+
// inline without re-parsing `content` (`ToolCard`'s `<img>`, per `assistant_demo_image`'s
|
|
150
|
+
// own doc). This does NOT remove the image block from `executed.output` — `image` is one
|
|
151
|
+
// of `tool-result-surfaces.ts`'s own `MODEL_VISIBLE_BLOCK_TYPES`, so the split below already
|
|
152
|
+
// keeps it in `modelOutput` on its own. An image reaching the model IS the point
|
|
153
|
+
// (`assistant_demo_image`/`admin.capture_screenshot` exist to prove exactly that round
|
|
154
|
+
// trip) — unlike an `mcp-ui` resource, which is genuinely human-only and must never survive
|
|
155
|
+
// into `modelOutput`. (Earlier this extraction fed its own de-imaged `remainder` into the
|
|
156
|
+
// surfaces split below and discarded the image from `output` entirely, on the assumption
|
|
157
|
+
// that the sibling `media` field was the only channel a caller needed — true for a UI
|
|
158
|
+
// reading the run's event stream, false for `@jini-ai/mcp`'s `execute_delegated_tool`, which
|
|
159
|
+
// hands the bridge's RETURN VALUE to the model with no access to that event stream at all.)
|
|
160
|
+
const { media } = extractResultMedia(executed.output);
|
|
161
|
+
// THE MODEL/HUMAN FORK. A tool call's return value is definitionally what the model
|
|
162
|
+
// receives, so a UI resource left inside it is model-visible context no matter what any
|
|
163
|
+
// downstream layer does — `@jini-ai/mcp`'s `okResult()` JSON.stringifies the whole result
|
|
164
|
+
// into a single text block. This is the only point holding BOTH the raw result and the
|
|
165
|
+
// run's event stream, which is why the split happens here rather than later.
|
|
166
|
+
//
|
|
167
|
+
// Whitelist, not blacklist: only block types known to be model-safe survive into `output`;
|
|
168
|
+
// everything else is withheld and emitted for the human. See `tool-result-surfaces.ts` for
|
|
169
|
+
// why that direction is load-bearing.
|
|
170
|
+
const { modelOutput, surfaces } = splitToolResultSurfaces(executed.output);
|
|
171
|
+
const result = surfaces.length === 0 ? executed : { ...executed, output: modelOutput };
|
|
172
|
+
// Emitted BEFORE `tool_result` so the surface is on screen by the time the transcript shows
|
|
173
|
+
// the call completing — otherwise the human is asked to confirm something not yet visible.
|
|
174
|
+
for (const surface of surfaces) {
|
|
175
|
+
await lifecycle.emit(runId, {
|
|
176
|
+
event: 'agent',
|
|
177
|
+
data: { type: MCP_UI_EVENT_TYPE, toolUseId, resource: surface },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
66
180
|
await lifecycle.emit(runId, {
|
|
67
181
|
event: 'agent',
|
|
68
182
|
data: {
|
|
@@ -70,11 +184,13 @@ export function createDelegatedToolBridge(options) {
|
|
|
70
184
|
toolUseId,
|
|
71
185
|
content: resultContent(result),
|
|
72
186
|
...(result.status === 'completed' ? {} : { isError: true }),
|
|
187
|
+
...(media.length > 0 ? { media } : {}),
|
|
73
188
|
},
|
|
74
189
|
});
|
|
75
190
|
return result;
|
|
76
191
|
}
|
|
77
192
|
catch (error) {
|
|
193
|
+
settled = true;
|
|
78
194
|
await lifecycle.emit(runId, {
|
|
79
195
|
event: 'agent',
|
|
80
196
|
data: { type: 'tool_result', toolUseId, content: errorMessage(error), isError: true },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delegated-tool-bridge.js","sourceRoot":"","sources":["../src/delegated-tool-bridge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"delegated-tool-bridge.js","sourceRoot":"","sources":["../src/delegated-tool-bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/event-log.d.ts
CHANGED
|
@@ -1,111 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `
|
|
2
|
+
* `createInMemoryEventLog` — the in-memory reference implementation of the `EventLog` port
|
|
3
|
+
* (extraction-plan §12 C1).
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* (
|
|
17
|
-
|
|
18
|
-
/** One durably-ordered record in a run's event log. */
|
|
19
|
-
export interface EventLogEntry<Payload = unknown> {
|
|
20
|
-
/** Monotonic per-run cursor, assigned by the log — never by the caller. */
|
|
21
|
-
readonly id: string;
|
|
22
|
-
readonly event: string;
|
|
23
|
-
readonly data: Payload;
|
|
24
|
-
/** Epoch-ms wall-clock time the entry was recorded. */
|
|
25
|
-
readonly recordedAt: number;
|
|
26
|
-
}
|
|
27
|
-
export interface EventLogAppendInput<Payload = unknown> {
|
|
28
|
-
readonly runId: string;
|
|
29
|
-
readonly event: string;
|
|
30
|
-
readonly data: Payload;
|
|
31
|
-
/**
|
|
32
|
-
* Optional producer-supplied dedup token. Appending twice with the same
|
|
33
|
-
* `dedupeKey` for the same run returns the original entry unchanged rather
|
|
34
|
-
* than recording a second one — this is what makes at-least-once producers
|
|
35
|
-
* (a retried emit after a timeout, a driver that re-delivers on
|
|
36
|
-
* reconnect) safe to layer on top of an otherwise plain ordered log.
|
|
37
|
-
*/
|
|
38
|
-
readonly dedupeKey?: string;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Result of `EventLog.replay`. `'ok'` and `'unknown-run'` are the two happy
|
|
42
|
-
* paths (a fresh run and a run this log has never heard of are both valid,
|
|
43
|
-
* un-exceptional states). `'replay-gap'` is the case OD's own ring buffer
|
|
44
|
-
* gets wrong today (see the module doc): the requested cursor references
|
|
45
|
-
* events that have already been evicted, so silently returning "whatever is
|
|
46
|
-
* still buffered" would hand the caller a stream with an undetectable hole
|
|
47
|
-
* in it. Making the gap a distinguishable result forces every caller
|
|
48
|
-
* (a transport reconnect handler, a test) to decide explicitly how to
|
|
49
|
-
* recover (full resync, error to the end user, etc.) instead of trusting
|
|
50
|
-
* data that looks contiguous but isn't. `'invalid-cursor'` covers a
|
|
51
|
-
* non-numeric cursor string, which is a caller/transport bug rather than a
|
|
52
|
-
* storage-shape problem and should not be conflated with a real gap.
|
|
53
|
-
*/
|
|
54
|
-
export type EventLogReplayResult<Payload = unknown> = {
|
|
55
|
-
readonly kind: 'ok';
|
|
56
|
-
readonly entries: readonly EventLogEntry<Payload>[];
|
|
57
|
-
/**
|
|
58
|
-
* `true` only when `afterCursor` was `null` (a first-time subscribe) AND this run's
|
|
59
|
-
* earliest entries have already been evicted, so `entries` starts after cursor 1 rather
|
|
60
|
-
* than at the true beginning. Omitted (not `false`) on every non-truncated result, so
|
|
61
|
-
* existing exact-match assertions against untruncated replays are unaffected. This does
|
|
62
|
-
* NOT make a first-time null-cursor replay a `'replay-gap'` — that would break the
|
|
63
|
-
* documented "nothing was ever promised to a caller that never asked" contract below and
|
|
64
|
-
* turn every legitimate first-time subscribe of a long-lived, intentionally-bounded run
|
|
65
|
-
* into a hard error. It exists so a caller that *cares* (a dashboard, a consumer with its
|
|
66
|
-
* own durability expectations) can distinguish "this run only ever had N events" from
|
|
67
|
-
* "this run had more, but some were evicted before I asked" instead of the two being
|
|
68
|
-
* silently indistinguishable on the wire.
|
|
69
|
-
*/
|
|
70
|
-
readonly truncated?: true;
|
|
71
|
-
} | {
|
|
72
|
-
readonly kind: 'replay-gap';
|
|
73
|
-
readonly requestedCursor: string;
|
|
74
|
-
/** The oldest cursor the log can still furnish, or `null` if the run's log is currently empty. */
|
|
75
|
-
readonly oldestAvailableCursor: string | null;
|
|
76
|
-
} | {
|
|
77
|
-
readonly kind: 'invalid-cursor';
|
|
78
|
-
readonly requestedCursor: string;
|
|
79
|
-
} | {
|
|
80
|
-
readonly kind: 'unknown-run';
|
|
81
|
-
};
|
|
82
|
-
/**
|
|
83
|
-
* A replayable, ordered, per-run event log. Kernel port — `@jini-ai/daemon`
|
|
84
|
-
* ships `createInMemoryEventLog` as the reference implementation; a durable
|
|
85
|
-
* adapter (`@jini-ai/sqlite`, task 8) implements the same interface.
|
|
5
|
+
* The port's own types (`EventLog`, `EventLogEntry`, `EventLogAppendInput`,
|
|
6
|
+
* `EventLogReplayResult`) moved to `@jini-ai/protocol` on 2026-07-29 so a storage adapter can
|
|
7
|
+
* implement them without depending on this runtime package — see that file's module doc. They are
|
|
8
|
+
* re-exported below, so every existing `import { EventLog } from '@jini-ai/daemon'` keeps working
|
|
9
|
+
* unchanged.
|
|
10
|
+
*
|
|
11
|
+
* OD's own event durability is split across three tiers today: a ~2000-event in-memory ring
|
|
12
|
+
* (`apps/daemon/src/runtimes/runs.ts` on the researched `arch/server-startserver-endgame` branch),
|
|
13
|
+
* a durable copy written into the product's own `messages.events_json` column, and a best-effort
|
|
14
|
+
* JSONL tail file that nothing ever reads back for replay. Because the durable half lives outside
|
|
15
|
+
* any port, a non-OD consumer that only wires the in-memory ring silently loses in-flight output
|
|
16
|
+
* on a long-run reload. `EventLog` is the fix: a single, storage-agnostic port that any adapter
|
|
17
|
+
* (this module's in-memory reference implementation, or `@jini-ai/sqlite`'s durable adapter)
|
|
18
|
+
* can satisfy.
|
|
86
19
|
*/
|
|
87
|
-
export
|
|
88
|
-
|
|
89
|
-
* Appends one event to `input.runId`'s ordered log.
|
|
90
|
-
*
|
|
91
|
-
* @returns The recorded entry (with its assigned cursor `id`), or the
|
|
92
|
-
* original entry unchanged if `input.dedupeKey` matches a prior append.
|
|
93
|
-
*/
|
|
94
|
-
append<Payload>(input: EventLogAppendInput<Payload>): Promise<EventLogEntry<Payload>>;
|
|
95
|
-
/**
|
|
96
|
-
* Returns every entry recorded after `afterCursor` for `runId`, or a
|
|
97
|
-
* distinguishable non-`'ok'` result — see {@link EventLogReplayResult}.
|
|
98
|
-
* `afterCursor: null` means "from the beginning of whatever is still
|
|
99
|
-
* retained" (a first-time subscribe, not a reconnect, so a run whose
|
|
100
|
-
* earliest events were already evicted before this call is not a gap —
|
|
101
|
-
* nothing was ever promised to this caller).
|
|
102
|
-
*/
|
|
103
|
-
replay(runId: string, afterCursor: string | null): Promise<EventLogReplayResult>;
|
|
104
|
-
/** Lists every run for which this log retains durable state. Used by a host at boot to rehydrate its `RunLifecycle` index. */
|
|
105
|
-
listRunIds(): Promise<readonly string[]>;
|
|
106
|
-
/** Discards all retained state for `runId` (e.g. once a terminal run's retention window has passed). */
|
|
107
|
-
drop(runId: string): Promise<void>;
|
|
108
|
-
}
|
|
20
|
+
export type { EventLog, EventLogAppendInput, EventLogEntry, EventLogReplayResult, } from '@jini-ai/protocol';
|
|
21
|
+
import type { EventLog } from '@jini-ai/protocol';
|
|
109
22
|
export interface InMemoryEventLogOptions {
|
|
110
23
|
/**
|
|
111
24
|
* Maximum entries retained per run before the oldest are evicted. Eviction is opt-in: if
|
package/dist/event-log.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-log.d.ts","sourceRoot":"","sources":["../src/event-log.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"event-log.d.ts","sourceRoot":"","sources":["../src/event-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,YAAY,EACV,QAAQ,EACR,mBAAmB,EACnB,aAAa,EACb,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,QAAQ,EAA4D,MAAM,mBAAmB,CAAC;AAE5G,MAAM,WAAW,uBAAuB;IACtC;;;;;;OAMG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAQD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,uBAA4B,GAAG,QAAQ,CAgFtF"}
|
package/dist/event-log.js
CHANGED
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `EventLog` — the durable event-log kernel port (extraction-plan §12 C1).
|
|
3
|
-
*
|
|
4
|
-
* OD's own event durability is split across three tiers today: a ~2000-event
|
|
5
|
-
* in-memory ring (`apps/daemon/src/runtimes/runs.ts` on the researched
|
|
6
|
-
* `arch/server-startserver-endgame` branch), a durable copy written into the
|
|
7
|
-
* product's own `messages.events_json` column, and a best-effort JSONL tail
|
|
8
|
-
* file that nothing ever reads back for replay. Because the durable half
|
|
9
|
-
* lives outside any port, a non-OD consumer that only wires the in-memory
|
|
10
|
-
* ring silently loses in-flight output on a long-run reload. `EventLog` is
|
|
11
|
-
* the fix: a single, storage-agnostic port that any adapter (this package's
|
|
12
|
-
* in-memory reference implementation, or `@jini-ai/sqlite`'s future durable
|
|
13
|
-
* adapter — task 8) can satisfy. Every method returns a `Promise` even
|
|
14
|
-
* though the in-memory implementation resolves synchronously, so a real
|
|
15
|
-
* persistent adapter is a drop-in swap rather than an API break
|
|
16
|
-
* (extraction-plan §2.6: "ports are async-only from day one").
|
|
17
|
-
*/
|
|
18
1
|
/**
|
|
19
2
|
* Reference `EventLog` implementation: a per-run FIFO array, optionally capped at
|
|
20
3
|
* `maxEntriesPerRun` (opt-in — see {@link InMemoryEventLogOptions}), functionally a ring
|
package/dist/event-log.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-log.js","sourceRoot":"","sources":["../src/event-log.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"event-log.js","sourceRoot":"","sources":["../src/event-log.ts"],"names":[],"mappings":"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"}
|
|
@@ -92,7 +92,7 @@ export interface CreateFrontendCapabilityRegistrationsOptions {
|
|
|
92
92
|
*
|
|
93
93
|
* @param options - The registry to route through, the manifest to expose, and the gate to apply.
|
|
94
94
|
* @returns Registrations in manifest order, ready to hand to a `ToolRegistry` (or to
|
|
95
|
-
* `@jini-ai/
|
|
95
|
+
* `@jini-ai/server`'s `toolRegistrations` config option).
|
|
96
96
|
* @throws Never. A duplicate id is reported by `ToolRegistry.register` at registration time,
|
|
97
97
|
* naming the id — this function does not pre-empt that with a second, differently-worded error.
|
|
98
98
|
*
|
|
@@ -37,7 +37,7 @@ function toCapabilityInput(capabilityId, input) {
|
|
|
37
37
|
*
|
|
38
38
|
* @param options - The registry to route through, the manifest to expose, and the gate to apply.
|
|
39
39
|
* @returns Registrations in manifest order, ready to hand to a `ToolRegistry` (or to
|
|
40
|
-
* `@jini-ai/
|
|
40
|
+
* `@jini-ai/server`'s `toolRegistrations` config option).
|
|
41
41
|
* @throws Never. A duplicate id is reported by `ToolRegistry.register` at registration time,
|
|
42
42
|
* naming the id — this function does not pre-empt that with a second, differently-worded error.
|
|
43
43
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontend-session-registry.d.ts","sourceRoot":"","sources":["../src/frontend-session-registry.ts"],"names":[],"mappings":"AAiDA,+FAA+F;AAC/F,MAAM,WAAW,yBAAyB;IACxC,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED,4EAA4E;AAC5E,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED,4EAA4E;AAC5E,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,MAAM,CACJ,UAAU,EAAE,yBAAyB,EACrC,OAAO,EAAE,CAAC,UAAU,EAAE,kBAAkB,KAAK,IAAI,GAChD,qBAAqB,CAAC;IACzB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IACtD;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAC7D;;;;;OAKG;IACH,MAAM,CACJ,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB;;;;;OAKG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC;IACnF;;;;OAIG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IAClD,uEAAuE;IACvE,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,yBAAyB,GAAG,SAAS,CAAC;CAClE;AAED,MAAM,WAAW,oCAAoC;IACnD,0FAA0F;IAC1F,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,MAAM,CAAC;CACtC;AAeD;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,GAAE,oCAAyC,GACjD,uBAAuB,
|
|
1
|
+
{"version":3,"file":"frontend-session-registry.d.ts","sourceRoot":"","sources":["../src/frontend-session-registry.ts"],"names":[],"mappings":"AAiDA,+FAA+F;AAC/F,MAAM,WAAW,yBAAyB;IACxC,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED,4EAA4E;AAC5E,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED,4EAA4E;AAC5E,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,MAAM,CACJ,UAAU,EAAE,yBAAyB,EACrC,OAAO,EAAE,CAAC,UAAU,EAAE,kBAAkB,KAAK,IAAI,GAChD,qBAAqB,CAAC;IACzB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IACtD;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAC7D;;;;;OAKG;IACH,MAAM,CACJ,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB;;;;;OAKG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC;IACnF;;;;OAIG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IAClD,uEAAuE;IACvE,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,yBAAyB,GAAG,SAAS,CAAC;CAClE;AAED,MAAM,WAAW,oCAAoC;IACnD,0FAA0F;IAC1F,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,MAAM,CAAC;CACtC;AAeD;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,GAAE,oCAAyC,GACjD,uBAAuB,CA+KzB"}
|
|
@@ -60,6 +60,15 @@ export function createFrontendSessionRegistry(options = {}) {
|
|
|
60
60
|
const newInvocationId = options.newInvocationId ?? randomUUID;
|
|
61
61
|
const newBindToken = options.newBindToken ?? randomUUID;
|
|
62
62
|
const sessions = new Map();
|
|
63
|
+
/**
|
|
64
|
+
* run id → the *attachment* serving it, deliberately not its session id.
|
|
65
|
+
*
|
|
66
|
+
* A session id is reusable by design: a surface that reconnects (tab reload, dropped stream)
|
|
67
|
+
* re-attaches under the same id, which is what makes the id useless as an ownership test. Keying
|
|
68
|
+
* on the attachment object makes every ownership comparison below identity-based, so a handle or
|
|
69
|
+
* unbind closure left over from a previous attachment is inert instead of silently unrouting the
|
|
70
|
+
* live surface that replaced it.
|
|
71
|
+
*/
|
|
63
72
|
const runBindings = new Map();
|
|
64
73
|
/** bind token → session id. Cleared on detach, so a token dies with the surface it proves. */
|
|
65
74
|
const bindTokens = new Map();
|
|
@@ -86,8 +95,7 @@ export function createFrontendSessionRegistry(options = {}) {
|
|
|
86
95
|
}
|
|
87
96
|
/** Resolves the surface that may serve this call, or explains precisely what is missing. */
|
|
88
97
|
function resolveTarget(runId, capabilityId) {
|
|
89
|
-
const
|
|
90
|
-
const session = sessionId === undefined ? undefined : sessions.get(sessionId);
|
|
98
|
+
const session = runBindings.get(runId);
|
|
91
99
|
if (session === undefined) {
|
|
92
100
|
throw new Error(`no frontend is bound to run "${runId}", so "${capabilityId}" cannot be executed`);
|
|
93
101
|
}
|
|
@@ -109,10 +117,17 @@ export function createFrontendSessionRegistry(options = {}) {
|
|
|
109
117
|
sessionId: descriptor.sessionId,
|
|
110
118
|
bindToken,
|
|
111
119
|
detach() {
|
|
112
|
-
|
|
120
|
+
// Only tear down state this attachment still owns. A stale handle — one whose attachment
|
|
121
|
+
// already detached and whose session id has since been re-attached — must not remove the
|
|
122
|
+
// replacement or its bindings; the replacement's own token/pending state is not this
|
|
123
|
+
// handle's to invalidate. `bindTokens` is safe to delete unconditionally: `bindToken` is
|
|
124
|
+
// minted per attachment, so this entry can only ever be this attachment's own.
|
|
125
|
+
const current = sessions.get(descriptor.sessionId);
|
|
113
126
|
bindTokens.delete(bindToken);
|
|
127
|
+
if (current === session)
|
|
128
|
+
sessions.delete(descriptor.sessionId);
|
|
114
129
|
for (const [runId, boundTo] of runBindings) {
|
|
115
|
-
if (boundTo ===
|
|
130
|
+
if (boundTo === session)
|
|
116
131
|
runBindings.delete(runId);
|
|
117
132
|
}
|
|
118
133
|
for (const [, entry] of session.pending) {
|
|
@@ -124,14 +139,16 @@ export function createFrontendSessionRegistry(options = {}) {
|
|
|
124
139
|
};
|
|
125
140
|
}
|
|
126
141
|
function bindRun(runId, sessionId) {
|
|
127
|
-
|
|
142
|
+
const session = sessions.get(sessionId);
|
|
143
|
+
if (session === undefined) {
|
|
128
144
|
throw new Error(`FrontendSessionRegistry: cannot bind run "${runId}" to unattached session "${sessionId}"`);
|
|
129
145
|
}
|
|
130
|
-
runBindings.set(runId,
|
|
146
|
+
runBindings.set(runId, session);
|
|
131
147
|
return () => {
|
|
132
148
|
// Only release a binding this call still owns: a run taken over by another surface must not
|
|
133
|
-
// have its newer binding torn down by the older one\'s cleanup.
|
|
134
|
-
|
|
149
|
+
// have its newer binding torn down by the older one\'s cleanup. Compared by attachment
|
|
150
|
+
// identity, not session id, so re-attaching under the same id also counts as a takeover.
|
|
151
|
+
if (runBindings.get(runId) === session)
|
|
135
152
|
runBindings.delete(runId);
|
|
136
153
|
};
|
|
137
154
|
}
|
|
@@ -190,8 +207,7 @@ export function createFrontendSessionRegistry(options = {}) {
|
|
|
190
207
|
return true;
|
|
191
208
|
}
|
|
192
209
|
function sessionFor(runId) {
|
|
193
|
-
|
|
194
|
-
return sessionId === undefined ? undefined : sessions.get(sessionId)?.descriptor;
|
|
210
|
+
return runBindings.get(runId)?.descriptor;
|
|
195
211
|
}
|
|
196
212
|
function capabilitiesFor(runId) {
|
|
197
213
|
return sessionFor(runId)?.capabilities ?? [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontend-session-registry.js","sourceRoot":"","sources":["../src/frontend-session-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA4IzC;;;;;;;;;GASG;AACH,MAAM,UAAU,6BAA6B,CAC3C,UAAgD,EAAE;IAElD,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,UAAU,CAAC;IAC9D,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,UAAU,CAAC;IACxD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IACpD,MAAM,WAAW,GAAG,IAAI,GAAG,
|
|
1
|
+
{"version":3,"file":"frontend-session-registry.js","sourceRoot":"","sources":["../src/frontend-session-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { RuntimeAgentDef } from '@jini-ai/agent-runtime';
|
|
2
|
+
/** The two values `applyImagePromptDelivery` actually changes — everything else about a run is untouched. */
|
|
3
|
+
export interface ImagePromptDelivery {
|
|
4
|
+
readonly prompt: string;
|
|
5
|
+
readonly extraAllowedDirs: readonly string[] | undefined;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Appends an attachments section to `prompt`, naming each image as a real
|
|
9
|
+
* file the user provided rather than dumping bare paths — legible to a
|
|
10
|
+
* model, which needs to understand these are attachments to read and act on,
|
|
11
|
+
* not incidental text. `imagePaths` must already be non-empty; callers (just
|
|
12
|
+
* `applyImagePromptDelivery` below) are expected to have filtered/checked
|
|
13
|
+
* that themselves so this function's own contract stays a straightforward
|
|
14
|
+
* "always augment" rather than duplicating the empty-check in two places.
|
|
15
|
+
*
|
|
16
|
+
* @param prompt - The user's original prompt text, unmodified up to this point.
|
|
17
|
+
* @param imagePaths - One or more absolute image file paths, already filtered non-empty.
|
|
18
|
+
* @returns `prompt` with an attachments section appended.
|
|
19
|
+
* @complexity O(n) in the number of images — one line rendered per path, no I/O.
|
|
20
|
+
* @overallScore 100
|
|
21
|
+
*/
|
|
22
|
+
export declare function augmentPromptWithImageAttachments(prompt: string, imagePaths: readonly string[]): string;
|
|
23
|
+
/**
|
|
24
|
+
* Directories a 'prompt-path' def's CLI must be allowed to read from so it
|
|
25
|
+
* can actually open the files the augmented prompt just told it about — the
|
|
26
|
+
* second half of the live-probe finding in `defs/claude.ts`'s module doc
|
|
27
|
+
* (the CLI refused the same path until its directory was allow-listed).
|
|
28
|
+
* Deduplicated, and order-stable (`Set` preserves insertion order) so a
|
|
29
|
+
* snapshot/equality test against the merged list is deterministic.
|
|
30
|
+
*
|
|
31
|
+
* @param imagePaths - One or more absolute image file paths, already filtered non-empty.
|
|
32
|
+
* @returns Each path's containing directory (`node:path#dirname`), deduplicated.
|
|
33
|
+
* @complexity O(n) in the number of images.
|
|
34
|
+
* @overallScore 100
|
|
35
|
+
*/
|
|
36
|
+
export declare function deriveImageAllowedDirs(imagePaths: readonly string[]): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Applies `'prompt-path'` image delivery when — and only when — `def`
|
|
39
|
+
* declares it and `imagePaths` is non-empty. Every other combination
|
|
40
|
+
* (`'native'`, `'unsupported'`, `undefined` delivery, or zero images on any
|
|
41
|
+
* def) returns `{ prompt, extraAllowedDirs }` completely unchanged, which is
|
|
42
|
+
* what keeps 'native' defs (ACP, pi-rpc, qoder) provably unaffected — this
|
|
43
|
+
* function is the single place that decides whether augmentation happens at
|
|
44
|
+
* all, so a 'native' def's `imageDelivery` value alone is what protects it
|
|
45
|
+
* from double delivery, not a second check duplicated at each call site.
|
|
46
|
+
*
|
|
47
|
+
* @param imageDelivery - `def.imageDelivery` — the def's own declared mode; pass this field directly rather than the whole def so this module has no dependency on `RuntimeAgentDef` beyond the one field's type.
|
|
48
|
+
* @param prompt - The user's original prompt text.
|
|
49
|
+
* @param imagePaths - The run's raw image paths, exactly as the caller received them (may be undefined/empty/contain blanks — this function does the filtering).
|
|
50
|
+
* @param extraAllowedDirs - The run's caller-supplied allowed directories, exactly as received.
|
|
51
|
+
* @returns The prompt and allowed-dirs to actually use for this run's `buildArgs`/prompt-delivery calls.
|
|
52
|
+
* @complexity O(n) in the number of images; O(1) when delivery is not `'prompt-path'` or there are no images.
|
|
53
|
+
* @overallScore 100
|
|
54
|
+
*/
|
|
55
|
+
export declare function applyImagePromptDelivery(imageDelivery: RuntimeAgentDef['imageDelivery'], prompt: string, imagePaths: readonly string[] | undefined, extraAllowedDirs: readonly string[] | undefined): ImagePromptDelivery;
|
|
56
|
+
//# sourceMappingURL=image-prompt-delivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-prompt-delivery.d.ts","sourceRoot":"","sources":["../src/image-prompt-delivery.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,6GAA6G;AAC7G,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CAC1D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CASvG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAE9E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,eAAe,CAAC,eAAe,CAAC,EAC/C,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACzC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAC9C,mBAAmB,CAarB"}
|