@plurnk/plurnk-a2a 1.9.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 (53) hide show
  1. package/.env.defaults +30 -0
  2. package/README.md +69 -0
  3. package/SPEC.md +199 -0
  4. package/dist/A2a.d.ts +12 -0
  5. package/dist/A2a.d.ts.map +1 -0
  6. package/dist/A2a.js +397 -0
  7. package/dist/A2a.js.map +1 -0
  8. package/dist/A2aMessage.d.ts +10 -0
  9. package/dist/A2aMessage.d.ts.map +1 -0
  10. package/dist/A2aMessage.js +28 -0
  11. package/dist/A2aMessage.js.map +1 -0
  12. package/dist/A2aProjection.d.ts +25 -0
  13. package/dist/A2aProjection.d.ts.map +1 -0
  14. package/dist/A2aProjection.js +183 -0
  15. package/dist/A2aProjection.js.map +1 -0
  16. package/dist/Functionality.d.ts +77 -0
  17. package/dist/Functionality.d.ts.map +1 -0
  18. package/dist/Functionality.js +247 -0
  19. package/dist/Functionality.js.map +1 -0
  20. package/dist/HttpJsonClient.d.ts +21 -0
  21. package/dist/HttpJsonClient.d.ts.map +1 -0
  22. package/dist/HttpJsonClient.js +41 -0
  23. package/dist/HttpJsonClient.js.map +1 -0
  24. package/dist/Module.d.ts +32 -0
  25. package/dist/Module.d.ts.map +1 -0
  26. package/dist/Module.js +91 -0
  27. package/dist/Module.js.map +1 -0
  28. package/dist/OutboundModule.d.ts +14 -0
  29. package/dist/OutboundModule.d.ts.map +1 -0
  30. package/dist/OutboundModule.js +24 -0
  31. package/dist/OutboundModule.js.map +1 -0
  32. package/dist/PlurnkAgentExecutor.d.ts +11 -0
  33. package/dist/PlurnkAgentExecutor.d.ts.map +1 -0
  34. package/dist/PlurnkAgentExecutor.js +282 -0
  35. package/dist/PlurnkAgentExecutor.js.map +1 -0
  36. package/dist/PlurnkTaskStore.d.ts +19 -0
  37. package/dist/PlurnkTaskStore.d.ts.map +1 -0
  38. package/dist/PlurnkTaskStore.js +271 -0
  39. package/dist/PlurnkTaskStore.js.map +1 -0
  40. package/dist/WorkspaceBinding.d.ts +13 -0
  41. package/dist/WorkspaceBinding.d.ts.map +1 -0
  42. package/dist/WorkspaceBinding.js +40 -0
  43. package/dist/WorkspaceBinding.js.map +1 -0
  44. package/dist/config.d.ts +22 -0
  45. package/dist/config.d.ts.map +1 -0
  46. package/dist/config.js +332 -0
  47. package/dist/config.js.map +1 -0
  48. package/dist/index.d.ts +10 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +9 -0
  51. package/dist/index.js.map +1 -0
  52. package/docs/a2a.md +23 -0
  53. package/package.json +66 -0
package/.env.defaults ADDED
@@ -0,0 +1,30 @@
1
+ # @plurnk/plurnk-a2a — outbound peers and optional inbound exposure.
2
+ # Alias blocks define available remote agents for every Worker's `agents` family;
3
+ # PLURNK_A2A_ENABLED selects the aliases enabled by default (a Worker may change
4
+ # its own enabledness through worker.agents.* or EXEC [agents]).
5
+ PLURNK_A2A_ENABLED=[]
6
+ PLURNK_A2A_CONNECT_TIMEOUT=30000
7
+ PLURNK_A2A_REQUEST_TIMEOUT=86400000
8
+
9
+ # PLURNK_A2A_RESEARCH=https://agent.example
10
+ # PLURNK_A2A_RESEARCH_CARD_PATH=/.well-known/agent-card.json
11
+ # PLURNK_A2A_RESEARCH_BEARER=${A2A_RESEARCH_TOKEN}
12
+ # PLURNK_A2A_RESEARCH_HEADERS={"X-Tenant":"${A2A_RESEARCH_TENANT}"}
13
+
14
+ # One optional Plurnk-hosted A2A exposure. Identity comes from this environment;
15
+ # protocol claims come from the implementation and cannot be configured falsely.
16
+ PLURNK_A2A_EXPOSE=0
17
+ PLURNK_A2A_HOST=127.0.0.1
18
+ PLURNK_A2A_PORT=4100
19
+ PLURNK_A2A_ENDPOINT_PATH=/a2a
20
+ PLURNK_A2A_ENDPOINT_URL=
21
+ PLURNK_A2A_WORKSPACE=a2a
22
+ PLURNK_A2A_PROJECT_ROOT=
23
+ PLURNK_A2A_NAME=
24
+ PLURNK_A2A_DESCRIPTION=
25
+ PLURNK_A2A_VERSION=
26
+ PLURNK_A2A_PROVIDER_ORGANIZATION=
27
+ PLURNK_A2A_PROVIDER_URL=
28
+ PLURNK_A2A_DOCUMENTATION_URL=
29
+ PLURNK_A2A_ICON_URL=
30
+ PLURNK_A2A_SKILLS=[]
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # @plurnk/plurnk-a2a
2
+
3
+ The A2A v1 exterior adapter for
4
+ [Plurnk](https://github.com/plurnk/plurnk-service). It exposes a Plurnk
5
+ workspace as an A2A agent and discovers remote agents through their standard
6
+ Agent Cards. The first implementation deliberately supports only the stable
7
+ HTTP+JSON v1 binding.
8
+
9
+ ## Expose an agent
10
+
11
+ The module is an exterior client of Core's `ApplicationPort`; it does not add
12
+ an A2A scheduler or Task database. The installed service reads the ordinary
13
+ Plurnk environment cascade. Enable one listener and describe its public
14
+ identity in an operator or project `.env`:
15
+
16
+ ```dotenv
17
+ PLURNK_A2A_EXPOSE=1
18
+ PLURNK_A2A_WORKSPACE=research
19
+ PLURNK_A2A_NAME="Research agent"
20
+ PLURNK_A2A_DESCRIPTION="Researches questions in its Plurnk workspace"
21
+ PLURNK_A2A_VERSION=1.0.0
22
+ PLURNK_A2A_SKILLS=[{"id":"research","name":"Research","description":"Researches a question and returns a sourced answer","tags":["research"]}]
23
+ ```
24
+
25
+ The module publishes the Agent Card at `/.well-known/agent-card.json` and the
26
+ advertised HTTP+JSON interface at `/a2a`. It rejects security declarations
27
+ until an authenticated exposure owns the corresponding enforcement path.
28
+ Starting the listener or reading its card does not create or hydrate the named
29
+ workspace; the first admitted Task does so.
30
+
31
+ ## Connect to an agent
32
+
33
+ ```ts
34
+ import { connectHttpJsonAgent } from "@plurnk/plurnk-a2a";
35
+
36
+ const client = await connectHttpJsonAgent("https://agent.example");
37
+ ```
38
+
39
+ Available remote agents use parallel alias blocks in the same environment
40
+ cascade. Their discovered standard Agent Cards remain authoritative:
41
+
42
+ ```dotenv
43
+ PLURNK_A2A_RESEARCH=https://agent.example
44
+ PLURNK_A2A_RESEARCH_BEARER=${A2A_RESEARCH_TOKEN}
45
+ PLURNK_A2A_ENABLED=["research"]
46
+ ```
47
+
48
+ In the service those definitions are the baseline of the Worker `agents`
49
+ Functionality family (`OutboundModule`): every Worker lists, discovers, adds,
50
+ enables, disables, and removes outbound agents through the common
51
+ `worker.agents.*` actions or the generated `EXEC [agents]` manager, and the
52
+ `a2a://<alias>` scheme resolves an alias against the Worker's own enabled
53
+ snapshot. Enabled agents appear in Turn 0 as one `worker://~/_plurnk/agents/<alias>.md`
54
+ catalog row each; the exact Agent Card stays pullable with `READ a2a://<alias>`.
55
+
56
+ The package also exports the outbound `a2a://` scheme handler for embedding.
57
+ Its resolver maps each URI authority, for the Worker the operation acts in, to
58
+ one client while keeping alias and credential policy outside the
59
+ protocol/resource owner:
60
+
61
+ ```ts
62
+ import { A2a, connectHttpJsonAgent } from "@plurnk/plurnk-a2a";
63
+
64
+ const scheme = new A2a(async (alias, ctx) =>
65
+ alias === "research" && ctx.functionalityWorkerId === 1 ? await connectHttpJsonAgent("https://agent.example") : null);
66
+ ```
67
+
68
+ Messages, Tasks, and Artifacts then use ordinary Plurnk entries and live
69
+ subscriptions. See [`SPEC.md`](./SPEC.md) for the current contract.
package/SPEC.md ADDED
@@ -0,0 +1,199 @@
1
+ # Plurnk A2A specification
2
+
3
+ ## §a2a-http-json-discovery HTTP+JSON discovery
4
+
5
+ `connectHttpJsonAgent` discovers the standard A2A Agent Card, selects an
6
+ advertised `HTTP+JSON` interface at protocol version `1.0`, and returns the
7
+ official SDK client. An explicit Agent Card path may replace the standard
8
+ well-known path. No legacy protocol or alternate binding is enabled.
9
+
10
+ ## §a2a-environment-projection POSIX configuration projection
11
+
12
+ The package `.env.defaults` is the complete configuration vocabulary. The
13
+ ordinary service, user, project, and client environment cascade remains the
14
+ only configuration authority; generated Agent Cards and discovered remote
15
+ cards are protocol projections, not configuration files.
16
+
17
+ | Family | Variables | Meaning |
18
+ |---|---|---|
19
+ | Outbound definition | `PLURNK_A2A_<ALIAS>=<absolute HTTP(S) URL>` plus optional `_CARD_PATH`, `_HEADERS`, and `_BEARER` companions | Defines one available remote agent without fetching or enabling it. `_BEARER` contains only a symbolic `${NAME}` reference; secrets remain environment-owned. |
20
+ | Outbound defaults | `PLURNK_A2A_ENABLED` | JSON array selecting the exact aliases enabled by default for a Worker's `agents` family ({§a2a-agents-functionality}); the Worker's durable state may override enabledness only. |
21
+ | Timeouts | `PLURNK_A2A_CONNECT_TIMEOUT`, `PLURNK_A2A_REQUEST_TIMEOUT` | Positive integer milliseconds owned by the A2A package. |
22
+ | Inbound listener | `PLURNK_A2A_EXPOSE`, `_HOST`, `_PORT`, `_ENDPOINT_PATH`, `_ENDPOINT_URL` | `EXPOSE=1` admits one optional HTTP+JSON listener; `0` admits none. |
23
+ | Inbound workspace | `PLURNK_A2A_WORKSPACE`, `_PROJECT_ROOT` | Names the lazily resolved execution workspace and its creation root. |
24
+ | Hosted identity | `PLURNK_A2A_NAME`, `_DESCRIPTION`, `_VERSION`, optional provider/docs/icon fields, and `_SKILLS` | Supplies identity content for one generated standard Agent Card. `_SKILLS` is a JSON array; omitted per-skill examples and media modes receive the exposure's factual defaults. |
25
+
26
+ Alias matching is case-insensitive but collision-intolerant, while the canonical
27
+ global names use their documented spelling. Header values preserve symbolic
28
+ environment references until connection admission. A remote Agent Card remains
29
+ the authority for that remote agent; its discovered contents are never copied
30
+ into this environment vocabulary.
31
+
32
+ ## §a2a-protocol-witness Protocol witness
33
+
34
+ The integration witness places a discovery-first client and an independent
35
+ agent on opposite sides of the official A2A v1 HTTP+JSON binding. It covers
36
+ card discovery, blocking task completion, task retrieval, ordered streaming
37
+ updates, cancellation, a direct Message without a fabricated Task,
38
+ input-required continuation under the same Task and Context identities,
39
+ multiple distinct Artifacts, and multiple Tasks sharing one Context. The
40
+ independent agent may use the SDK's reference request handler and task store;
41
+ those test actors establish wire behavior and are not the Plurnk task
42
+ architecture.
43
+
44
+ ## §a2a-inbound-exposure Inbound exterior exposure
45
+
46
+ The inbound HTTP+JSON listener is an exterior adapter over
47
+ `ApplicationPort`. The official SDK owns A2A framing and request handling;
48
+ Plurnk Workers, Loops, logs, and terminal results remain the only execution
49
+ state. The SDK `TaskStore` implementation is a projection of that durable
50
+ state, not an independent Task database.
51
+
52
+ ```mermaid
53
+ flowchart LR
54
+ Caller["A2A caller"] --> Context["Context root Worker\nname = contextId"]
55
+ Context --> Task1["Task child Worker\nname = taskId"]
56
+ Context --> Task2["Task child Worker\nname = taskId"]
57
+ Task1 --> Loop1["one live Task Loop"]
58
+ Task2 --> Loop2["one live Task Loop"]
59
+ ```
60
+
61
+ The SDK generates new Context and Task UUIDs before execution. Those UUIDs
62
+ already satisfy Plurnk's worker-name contract, so their exact values name the
63
+ root Context Worker and its Task child. No adapter binding table, synthetic
64
+ actor, or second scheduler exists. Later Tasks fork the Context root and
65
+ therefore receive the parent-visible prior Task evidence under Core's ordinary
66
+ topology contract.
67
+
68
+ Only a child Worker with a durable prompt source matching its exact A2A Context,
69
+ Task, and Message identities projects as a Task. A root is reusable as an A2A
70
+ Context only after this adapter created it in the running exposure or one such
71
+ Task proves its durable ownership after restart. Ordinary model Workers in the
72
+ same workspace are neither discoverable nor adoptable through A2A. A request
73
+ rejected before Worker admission may yield the official SDK's ephemeral failed
74
+ Task response, but it creates no durable Task state.
75
+
76
+ | Durable Plurnk state | A2A projection |
77
+ |---|---|
78
+ | Loop `100` | `SUBMITTED` |
79
+ | Loop `102` or `202` | `WORKING`; parking alone does not claim user input is required |
80
+ | Pending client interaction on the Task Loop | `INPUT_REQUIRED` |
81
+ | Successful terminal result | `COMPLETED`; a non-empty final SEND is the `result` Artifact |
82
+ | External cancellation / Loop `499` | `CANCELED` |
83
+ | Other terminal failure | `FAILED` with the exact Problem detail as its status Message |
84
+ | Prompt rows carrying the adapter's causal source | User Message history |
85
+
86
+ The first exposure accepts only text Message Parts, advertises HTTP+JSON v1
87
+ streaming without push notifications, tenants, extended cards, or security
88
+ schemes, and rejects a card that claims unsupported security. Those omitted
89
+ surfaces are not silently simulated. The adapter subscribes to live
90
+ application events for streaming and reads durable Worker/Loop/log projections
91
+ for retrieval and restart truth.
92
+
93
+ §a2a-hosted-card The service generates the hosted standard Agent Card from
94
+ normalized environment identity plus actual adapter capabilities. The adapter,
95
+ not configuration, fixes HTTP+JSON protocol `1.0`, streaming, no push
96
+ notifications, no extended card, no tenant, no security, `text/plain` input,
97
+ and `text/markdown` output. Unsupported security claims are structurally absent
98
+ rather than configurable. The official SDK serializes the card served at the
99
+ standard well-known path.
100
+
101
+ §a2a-lazy-workspace Listener startup and Agent Card discovery perform no
102
+ workspace creation, attachment, hydration, model selection, or inference. The
103
+ first admitted Task resolves the configured workspace name, adopting the one
104
+ existing match or creating it with the configured project root. A configured
105
+ non-null root must match an existing workspace exactly. The resolution is
106
+ shared across concurrent requests and a failed resolution remains retryable.
107
+
108
+ ## §a2a-agents-functionality Outbound agents as Worker Functionality
109
+
110
+ The package registers, through `OutboundModule`, the `a2a` resource scheme and
111
+ one Worker Functionality family named `agents` ({§functionality-adapter} in
112
+ core). The family is not tagged `a2a` because every executor tag is also a
113
+ scheme face and would collide with the `a2a://` resource scheme. Its definition
114
+ is the `A2aAgentDefinition` contract — local alias `name`, remote `url`,
115
+ optional `cardPath`, `headers`, and symbolic bearer `authorization` —
116
+ exactly the environment's `PLURNK_A2A_<ALIAS>*` projection.
117
+
118
+ *Available definitions* are the environment's aliases; `PLURNK_A2A_ENABLED`
119
+ supplies their default enabledness. *Admission* (`add {alias, definition}`)
120
+ requires `alias = name`. *Discovery is inert*: `discover {source}` fetches one
121
+ standard Agent Card from that URL only and returns one candidate whose alias
122
+ is the card name's slug, with `agent-card` provenance; `discover
123
+ {configuration}` projects a client's own `PLURNK_A2A_*` environment as
124
+ `client-configuration` candidates; `discover {query}` is 501
125
+ `registry-not-configured` until a registry is configured. Discovery never
126
+ adds, enables, authenticates beyond the named host, or persists.
127
+
128
+ *Preparation* resolves symbolic `${NAME}` references at connection
129
+ (`authorization-unresolved` when absent), discovers and validates the standard
130
+ Agent Card at the definition's URL (`card-unreachable`), and connects only
131
+ through an advertised HTTP+JSON `1.0` interface (`interface-unsupported`),
132
+ reusing an unchanged attachment across publications. The outcome detail carries
133
+ the card's name, version, description, skill identifiers, and streaming
134
+ capability. The family publishes no runtimes; its snapshot is the Worker's
135
+ `alias → client` map, and the `a2a` scheme resolves an authority against the
136
+ Functionality of the Worker the operation acts in (`ctx.functionalityWorkerId`):
137
+ an unknown or disabled alias is 404 `agent-not-configured`, an unavailable
138
+ alias carries its one exact preparation Problem, and two Workers may hold the
139
+ same textual alias with different definitions and credentials.
140
+
141
+ §a2a-agents-catalog **Turn 0 shows enabled agents concisely.** Preparation
142
+ publishes one `worker://~/_plurnk/agents/<alias>.md` document per active
143
+ alias — an H1 alias, an H2 `Summary` whose one line is
144
+ `a2a://<alias> — <card name> v<version>: <description>`, and the invocation
145
+ form — and nothing for disabled or unavailable aliases. Core's seventh turn-0
146
+ survey (`## FIND0 [+init,+agents] (worker://~/_plurnk/agents/*.md) <1,-1>`,
147
+ {§actor-boundary-catalog-preview}) therefore presents every effective agent as
148
+ one summary row. The document embeds neither the card nor its skills; both stay
149
+ pullable exactly through `READ a2a://<alias>` ({§a2a-outbound-definition}).
150
+ Hosted inbound exposure ({§a2a-inbound-exposure}) is unaffected by this family.
151
+
152
+ ## §a2a-outbound-resources Outbound resources
153
+
154
+ The `a2a` scheme is an exterior client adapter over ordinary Plurnk resource
155
+ and subscription contracts. Its URI authority is the configured remote-agent
156
+ alias. The adapter is not a Worker producer, scheduler, Task store, or alternate
157
+ operation runtime.
158
+
159
+ §a2a-outbound-definition An enabled outbound alias resolves through its
160
+ Worker's `agents` Functionality snapshot ({§a2a-agents-functionality}), whose
161
+ preparation discovered and validated the remote standard Agent Card and
162
+ selected only an advertised HTTP+JSON `1.0` interface. The local alias,
163
+ target, optional card path, symbolic authentication, and provenance are local
164
+ configuration; the discovered card's identity, capabilities, skills, and
165
+ interfaces remain remote protocol authority.
166
+
167
+ | Operation | Target | Result |
168
+ |---|---|---|
169
+ | READ | `a2a://<agent>` | Materialize the discovered Agent Card. |
170
+ | SEND `[200]` | `a2a://<agent>` | Send a new user Message. A direct Message creates one static `/messages/<id>` resource and returns `200`; a Task creates one live `/tasks/<id>` resource and returns `102`. |
171
+ | SEND `[200]` | Exact `/tasks/<id>` resource | Continue the same non-terminal Task identity, including an input-required or auth-required Task. |
172
+ | SEND `[499]` | Live Task resource | Cancel the ordinary local subscription, which requests cancellation of the remote Task. |
173
+ | READ | Exact Task or Artifact resource | Materialize the remote resource's current canonical snapshot. |
174
+
175
+ §a2a-outbound-turn-rhythm A Task-backed call composes through ordinary model
176
+ turns rather than an adapter-authored continuation. The directed disposition
177
+ SEND is structurally the end of its emission ({§send-mid-reservation}), but its
178
+ target makes `[200]` the A2A operation code rather than the local Loop
179
+ disposition. Core therefore routes the request and naturally presents its
180
+ `102` Task receipt in the next turn. If the model then chooses to wait, a
181
+ pathless `SEND [202]` parks the Loop; subscription completion wakes that same
182
+ Loop with the exact terminal READ, after which a pathless `SEND [200]` may
183
+ conclude under {§wait-obligation-matrix}. No hidden adapter turn or synthetic
184
+ local disposition fills any step.
185
+
186
+ Task-backed calls use Core's ordinary live-resource path: the scheme seeds one
187
+ entry, opens one subscription, returns its exact address with `102`, and closes
188
+ that subscription with the remote Task result. Core alone owns parking, waking,
189
+ the terminal next-turn READ, and cancellation propagation.
190
+
191
+ ## §a2a-resource-projection Resource projection
192
+
193
+ Every retained Agent Card, Message, Task, and Artifact has a model-oriented
194
+ Markdown `#body` and an exact protocol `#json` channel serialized by the pinned
195
+ official SDK. A Task's Artifact identities remain distinct URI descendants and
196
+ materialize independently; the adapter never flattens multiple Artifacts into
197
+ one fabricated result. Projection wording is presentation rather than protocol
198
+ identity: tests assert lifecycle state, content, media type, and addressability,
199
+ not a prose template.
package/dist/A2a.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { Client } from "@a2a-js/sdk/client";
2
+ import { type PassthroughResult, type RepresentationPreparationRequest, type RepresentationPreparationResult, type SchemeCtx, type SchemeHandler, type SchemeManifest, type SendStatement } from "@plurnk/plurnk-schemes";
3
+ export type A2aClientResolver = (authority: string, ctx: SchemeCtx) => Client | null | Promise<Client | null>;
4
+ /** Outbound A2A v1 resources and Task obligations over the ordinary scheme API. */
5
+ export default class A2a implements SchemeHandler {
6
+ #private;
7
+ static manifest: SchemeManifest;
8
+ constructor(resolveClient: A2aClientResolver);
9
+ prepareRepresentation(request: RepresentationPreparationRequest, ctx: SchemeCtx): Promise<RepresentationPreparationResult>;
10
+ send(statement: SendStatement, ctx: SchemeCtx): Promise<PassthroughResult>;
11
+ }
12
+ //# sourceMappingURL=A2a.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"A2a.d.ts","sourceRoot":"","sources":["../src/A2a.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAIH,KAAK,iBAAiB,EACtB,KAAK,gCAAgC,EACrC,KAAK,+BAA+B,EACpC,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,cAAc,EAEnB,KAAK,aAAa,EAErB,MAAM,wBAAwB,CAAC;AAUhC,MAAM,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAe9G,mFAAmF;AACnF,MAAM,CAAC,OAAO,OAAO,GAAI,YAAW,aAAa;;IAC7C,MAAM,CAAC,QAAQ,EAAE,cAAc,CAmB7B;IAIF,YAAY,aAAa,EAAE,iBAAiB,EAE3C;IAEK,qBAAqB,CACvB,OAAO,EAAE,gCAAgC,EACzC,GAAG,EAAE,SAAS,GACf,OAAO,CAAC,+BAA+B,CAAC,CAgE1C;IAEK,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA+G/E;CAyNJ"}