@skillstate/opencode 2.2.2 → 3.0.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.
Files changed (62) hide show
  1. package/README.md +194 -142
  2. package/dist/feedback.d.ts +178 -0
  3. package/dist/feedback.d.ts.map +1 -0
  4. package/dist/feedback.js +235 -0
  5. package/dist/feedback.js.map +1 -0
  6. package/dist/index.d.ts +58 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +48 -3
  9. package/dist/index.js.map +1 -1
  10. package/dist/mode.d.ts +97 -0
  11. package/dist/mode.d.ts.map +1 -0
  12. package/dist/mode.js +111 -0
  13. package/dist/mode.js.map +1 -0
  14. package/dist/opencode-adapter.d.ts +10 -46
  15. package/dist/opencode-adapter.d.ts.map +1 -1
  16. package/dist/opencode-adapter.js +1 -64
  17. package/dist/opencode-adapter.js.map +1 -1
  18. package/dist/paper-mode.d.ts +421 -0
  19. package/dist/paper-mode.d.ts.map +1 -0
  20. package/dist/paper-mode.js +445 -0
  21. package/dist/paper-mode.js.map +1 -0
  22. package/dist/plugin.d.ts +218 -76
  23. package/dist/plugin.d.ts.map +1 -1
  24. package/dist/plugin.js +867 -232
  25. package/dist/plugin.js.map +1 -1
  26. package/dist/response-sink.d.ts +208 -0
  27. package/dist/response-sink.d.ts.map +1 -0
  28. package/dist/response-sink.js +243 -0
  29. package/dist/response-sink.js.map +1 -0
  30. package/dist/runtime.d.ts +203 -0
  31. package/dist/runtime.d.ts.map +1 -0
  32. package/dist/runtime.js +332 -0
  33. package/dist/runtime.js.map +1 -0
  34. package/dist/session-registry.d.ts +148 -0
  35. package/dist/session-registry.d.ts.map +1 -0
  36. package/dist/session-registry.js +236 -0
  37. package/dist/session-registry.js.map +1 -0
  38. package/dist/spec-loader.d.ts +81 -0
  39. package/dist/spec-loader.d.ts.map +1 -0
  40. package/dist/spec-loader.js +163 -0
  41. package/dist/spec-loader.js.map +1 -0
  42. package/dist/state-store.d.ts +126 -0
  43. package/dist/state-store.d.ts.map +1 -0
  44. package/dist/state-store.js +186 -0
  45. package/dist/state-store.js.map +1 -0
  46. package/dist/step-boundary.d.ts +91 -0
  47. package/dist/step-boundary.d.ts.map +1 -0
  48. package/dist/step-boundary.js +109 -0
  49. package/dist/step-boundary.js.map +1 -0
  50. package/dist/system-hint.d.ts +129 -0
  51. package/dist/system-hint.d.ts.map +1 -0
  52. package/dist/system-hint.js +166 -0
  53. package/dist/system-hint.js.map +1 -0
  54. package/dist/tools.d.ts +148 -0
  55. package/dist/tools.d.ts.map +1 -0
  56. package/dist/tools.js +350 -0
  57. package/dist/tools.js.map +1 -0
  58. package/package.json +3 -2
  59. package/dist/plugin-types.d.ts +0 -71
  60. package/dist/plugin-types.d.ts.map +0 -1
  61. package/dist/plugin-types.js +0 -8
  62. package/dist/plugin-types.js.map +0 -1
package/dist/plugin.d.ts CHANGED
@@ -1,95 +1,237 @@
1
- import { mergePatch, resolveHostStateForCwd } from '@skillstate/core';
2
- import type { OpenCodeMessage, SkillStatePlugin } from './plugin-types.js';
3
- export * from './plugin-types.js';
4
1
  /**
5
- * Resolve the per-project state file for a session working directory
6
- * (`cwd` of the current opencode session) — the core single source of
7
- * truth (`resolveHostStateForCwd`): `<cwd>/.skillstate/skillstate.json`,
8
- * or the global bucket `<home>/.skillstate/global/skillstate.json` when
9
- * cwd equals home. A non-empty `agentId` scopes the file under
10
- * `<bucket>/agents/<agentId>/skillstate.json`. Pure path arithmetic via
11
- * `path.resolve`, no filesystem access.
2
+ * `@skillstate/opencode` — the OpenCode **v2** plugin.
3
+ *
4
+ * ── What this replaces ───────────────────────────────────────────────────
5
+ *
6
+ * The v1 integration rewrote the conversation on every model request. It
7
+ * kept the system messages and the last three non-system messages, dropped
8
+ * everything else from `output.messages`, and appended a synthetic
9
+ * `role: "user"` message containing the raw state JSON. The reported
10
+ * failure was that the agent stopped doing the user's task and started
11
+ * emitting state JSON instead.
12
+ *
13
+ * Both halves of that were destructive, and neither was a model quirk:
14
+ *
15
+ * 1. The injected message landed LAST, so for the model it was the current
16
+ * instruction — it displaced the user's actual request.
17
+ * 2. `slice(-3)` deleted the task statement, the tool results and the
18
+ * errors the agent had just been handed. It was reasoning about work it
19
+ * could no longer see.
20
+ *
21
+ * The MCP server made it worse: `spec.get` returned a procedural spec whose
22
+ * default was `INTERCODE_CTF_SPEC`, whose instructions read "You are an
23
+ * autonomous CTF agent ... hidden flag somewhere on its filesystem". A
24
+ * model told to look for a flag looks for a flag. (Fixed: the default is now
25
+ * the neutral `GENERIC_PROCEDURE_SPEC`, and its instructions describe the
26
+ * storage format instead of prescribing a way of working.)
27
+ *
28
+ * ── The v2 design ────────────────────────────────────────────────────────
29
+ *
30
+ * Two modes, each enforced by a test. They are different contracts with the
31
+ * model, not variants of one behaviour:
32
+ *
33
+ * - **`notes` (default).** Contribute one additive, bounded fragment to
34
+ * `event.system` and leave the transcript alone. The agent sees its own
35
+ * history the way the host intends, and the saved notes ride alongside it.
36
+ * This is the mode that fixed the v1 failure, and it is the default for
37
+ * exactly that reason.
38
+ * - **`paper` (opt-in).** Replace the model-facing context with
39
+ * Aₜ = (P, Σₜ, Oₜ) — the paper's Appendix A.4 prompt, byte-verbatim — and
40
+ * apply the `state_patch` the model emits in response. This is the paper's
41
+ * specification, and it is a real behavioural change: the model stops
42
+ * seeing its transcript, because §3.2 discards the reasoning trace by
43
+ * construction. Select it with `mode: "paper"` in the project's
44
+ * `skillstate.json` or `SKILLSTATE_MODE=paper`; see `mode.ts`.
45
+ *
46
+ * The default is `notes` and must stay that way: a default that discards the
47
+ * user's task is the v1 bug under a new name.
48
+ *
49
+ * Three rules, each enforced by a test:
50
+ *
51
+ * - **Notes mode never mutates `event.messages`.** The plugin contributes
52
+ * one additive fragment to `event.system` and leaves the transcript alone.
53
+ * See `tests/opencode/context-integrity.test.ts`.
54
+ * - **Never inject behavioural instructions in notes mode.** The system
55
+ * fragment describes what the notes are and when to use them; it contains
56
+ * no "you must", no "always", and no output format. See
57
+ * `system-hint.ts`.
58
+ * - **Inert until used.** A project with no state file gets no system
59
+ * fragment at all and behaves exactly like vanilla OpenCode. No files are
60
+ * created by loading the plugin.
61
+ *
62
+ * ── Native tools AND the MCP server, on purpose ──────────────────────────
63
+ *
64
+ * This package does not replace `@skillstate/mcp`; it sits beside it.
65
+ *
66
+ * - The native tools ({@link registerTools}) are the fast path inside
67
+ * opencode: a typed schema, structured output, no JSON-RPC round-trip and
68
+ * no untyped text result.
69
+ * - The MCP server is the portable path. It is what every other
70
+ * MCP-capable host reads, and the only way to reach this state from a
71
+ * client that is not opencode.
72
+ *
73
+ * Both address the same `<project>/.skillstate/skillstate.json`, so they
74
+ * cannot disagree about what is saved. `skillstate init` registers both.
75
+ *
76
+ * The reason v1 needed the MCP server is gone: an opencode v1 plugin could
77
+ * not contribute first-class tools at all.
78
+ *
79
+ * Load it from `opencode.json(c)`:
80
+ *
81
+ * ```json
82
+ * { "plugins": ["@skillstate/opencode"] }
83
+ * ```
12
84
  */
13
- export { resolveHostStateForCwd as resolveStatePathForCwd };
14
- export { mergePatch };
15
- /** Options for {@link createSkillStatePlugin}. */
16
- export interface SkillStatePluginOptions {
17
- /** Non-system messages kept in the prompt (default 3). */
18
- maxHistoryMessages?: number;
19
- }
85
+ import { Plugin } from '@opencode/plugin';
86
+ /** Stable plugin id — scopes plugin storage and identifies it in `/api/plugin`. */
87
+ export declare const PLUGIN_ID = "skillstate";
20
88
  /**
21
- * Read the state file. Missing or corrupt files yield `{}` (best-effort).
22
- * The on-disk envelope is `{ version: 1, state }` (migrations-compatible);
23
- * a bare object is tolerated and treated as the state itself. Thin fs
24
- * adapter over the core hook-runtime {@link readStateEnvelope}.
89
+ * The action carried forward when a turn produced no usable patch.
90
+ *
91
+ * NOT `__invalid_patch__`, though the paper names that sentinel at §5.1 line
92
+ * 9. It is a return value there — what the step function hands back to signal
93
+ * that Σ is unchanged — and forwarding it into the prompt as the next action
94
+ * is meaningless to a model: it is a name, not a request. The retry instruction
95
+ * the model actually needs already rides in Oₜ through the feedback queue, so
96
+ * this only has to say "keep going", and the queue says why.
25
97
  */
26
- export declare function readSkillState(statePath: string): Record<string, unknown>;
98
+ export declare const CONTINUE_ACTION = "continue";
27
99
  /**
28
- * Persist the state file (best-effort: read-only environments are ignored).
29
- * Creates the parent directory when missing (the per-project resolver may
30
- * target a fresh `<cwd>/.skillstate/agents/<id>/`). Writes the
31
- * `{ version: 1, state }` envelope so `migrate()`/runtime resume read the
32
- * same file — via the core hook-runtime {@link saveStateEnvelope} — under
33
- * the cross-process sync lock {@link lockStateWrite} (2-3 parallel agent
34
- * processes never interleave state writes).
100
+ * Record every event type the plugin actually receives.
101
+ *
102
+ * @non-paper diagnostics, same file. The advance is triggered by one event
103
+ * type and one, and a trigger that never fires is indistinguishable from one
104
+ * that is wired wrong — so the arrival counts have to be visible. Cheap, and
105
+ * it would have saved guessing.
35
106
  */
36
- export declare function saveSkillState(statePath: string, state: Record<string, unknown>): void;
107
+ export declare function recordEvent(path: string | undefined, type: string): void;
37
108
  /**
38
- * Atomic READ-MERGE-WRITE of one `state_patch` (paper ⊕: null deletes):
39
- * the whole critical section runs inside {@link lockStateWrite}, so two
40
- * concurrent writers apply BOTH patches instead of racing between the
41
- * read and the write. Best-effort: lock contention or unwritable state
42
- * files are swallowed — the tool flow never breaks.
109
+ * Whether the host has just executed a tool for this request.
110
+ *
111
+ * A tool result in the transcript is the observable edge of "an action ran".
112
+ * There is no event that says so in a shape this plugin can trust — and an
113
+ * event the host does not wait for is what caused the read-after-write race
114
+ * fixed in `response-sink.ts`, so the transcript is the more reliable of the
115
+ * two here as well as the more available one.
43
116
  */
44
- export declare function mergeSkillState(statePath: string, patch: Record<string, unknown>): Record<string, unknown>;
117
+ /** Tool-result parts in the newest tool message, counted. */
118
+ export declare function countToolResults(messages: ReadonlyArray<{
119
+ role: string;
120
+ content: unknown;
121
+ }>): number;
45
122
  /**
46
- * Extract the `state_patch` object from an LLM response's fenced ```json
47
- * block; `null` when there is no block, it is malformed, or it carries no
48
- * object-shaped `state_patch`. Thin adapter over the core hook-runtime
49
- * {@link findFencedPatch} (the invalid/truncated outcomes collapse to
50
- * `null`, preserving the legacy boolean contract).
123
+ * Append what the host actually handed us to a file, for diagnosis.
124
+ *
125
+ * @non-paper diagnostics. Enabled by `SKILLSTATE_DEBUG_PROMPT=<path>`.
126
+ *
127
+ * This exists because of a bug that was invisible from the inside for a
128
+ * long time. The model would run a tool, get the answer, and never record
129
+ * it — which looks exactly like a model refusing to cooperate, and sent the
130
+ * search through prompt slots, model choice and spec wording. The cause was
131
+ * the SHAPE: OpenCode v2 delivers a tool result as
132
+ * `{ type: 'tool-result', result: { value } }`, so a reader that only knew
133
+ * `{ type: 'text', text }` made Oₜ permanently empty without ever throwing.
134
+ *
135
+ * The dump records the part types alongside the extracted text, so that
136
+ * class of failure is visible on sight: a `tool-result` in the list next to
137
+ * an empty `observation` says the reader, not the model, is at fault.
138
+ *
139
+ * Append-only so a session's turns accumulate in order, and every failure
140
+ * is swallowed — diagnostics must never break the agent loop.
51
141
  */
52
- export declare function extractPatch(response: string): Record<string, unknown> | null;
142
+ export declare function dumpPromptShape(path: string | undefined, messages: ReadonlyArray<{
143
+ role: string;
144
+ content: unknown;
145
+ }>, state?: Record<string, unknown>): void;
53
146
  /**
54
- * Agent id for an opencode hook call.
55
- *
56
- * MAIN SESSION → `''` (the ROOT state file `<cwd>/.skillstate/skillstate.json`
57
- * — the SAME file the skillstate MCP tools and the CLI address, so the
58
- * injected state and `state.patch` can never disagree). A session
59
- * registered as a SUB-AGENT via the host event bus
60
- * (`session.created`/`updated` carry `info.parentID`) resolves to
61
- * `<parentPrefix>-<sessionPrefix>` — an isolated copy under `agents/` that
62
- * never last-writer-wins the main state; the main agent folds it back with
63
- * `agent.merge`. No session id at all → `''` (root: a single context).
147
+ * One line per turn of the anti-drift diagnostic.
148
+ *
149
+ * The drift notice has a claim attached to it — "the model drifts, the notice
150
+ * brings it back" — and neither half can be checked from inside the process.
151
+ * A notice in a prompt is not an observation of a model: the fragment may be
152
+ * built correctly and the model may ignore it, and the two look identical
153
+ * from the code's side. Worse, both look identical from the *outside* too,
154
+ * which is what made the earlier `tool-result` bug so expensive to find.
155
+ *
156
+ * So each line carries the evidence that distinguishes them:
157
+ *
158
+ * - `notice` — was the drift sentence in the fragment that went out this turn;
159
+ * - `writes` — how many times the state file had changed when it went out, so
160
+ * a notice that repeats forever is visible as a flat counter;
161
+ * - `fragments` — how many turns had passed without a change.
162
+ *
163
+ * That is enough to say "the notice fired and the state moved afterwards" or
164
+ * "the notice fired and nothing happened", which is the only claim worth
165
+ * making about it.
166
+ *
167
+ * @non-paper diagnostics. Enabled by `SKILLSTATE_DEBUG_DRIFT=<path>`.
168
+ * Separate from {@link dumpPromptShape} because it answers a different
169
+ * question: that one asks what the host sent, this one asks what the model
170
+ * did about what we sent.
64
171
  */
65
- export declare function pluginAgentId(input: {
66
- sessionID?: unknown;
67
- }, messages?: OpenCodeMessage[]): string;
172
+ export declare function dumpDrift(path: string | undefined, record: {
173
+ readonly scope: string;
174
+ readonly turns: number;
175
+ readonly notice: boolean;
176
+ readonly writes: number;
177
+ }): void;
68
178
  /**
69
- * Widen an agent id for a registered sub-agent session:
70
- * `<parentPrefix>-<sessionPrefix>`. Plain sessions resolve to `''` (the
71
- * main/root scope — NOT their own agents/ copy).
179
+ * One line per step, for the run that answered correctly while its state
180
+ * under-reported the work. Enabled by `SKILLSTATE_DEBUG_STEPS=<path>`.
181
+ *
182
+ * The 30-file measurement produced the most confusing result in this project's
183
+ * history: paper mode answered correctly, its state ended 25/30, and the
184
+ * control's ended 30/30 complete. Twenty-five patches were emitted and all
185
+ * twenty-five landed, so no patch was lost — the model read every file and
186
+ * declined to patch the last five, while the loop kept driving it. From the
187
+ * outside that is indistinguishable from the loop stopping, from the model
188
+ * silently abandoning the protocol, and from the ceiling being hit.
189
+ *
190
+ * So this prints the thing that tells those apart: at every step, whether a
191
+ * patch was applied, what the state looked like, and whether the driver asked
192
+ * again. Every previous wrong guess in this file came from reasoning about the
193
+ * loop instead of watching it.
72
194
  */
73
- export declare function scopedAgentId(agentId: string): string;
195
+ export declare function dumpStepTrace(path: string | undefined, record: {
196
+ readonly sessionID: string;
197
+ readonly step: number;
198
+ readonly attempt: number;
199
+ readonly applied: boolean;
200
+ readonly done: number;
201
+ readonly total: number | null;
202
+ readonly drove: boolean;
203
+ readonly note: string;
204
+ }): void;
74
205
  /**
75
- * Record a session→parent edge from the host event stream. `sessionId`
76
- * with a non-empty `parentID` registers that session as a sub-agent of
77
- * `parentID`; an empty `parentID` (the main session being updated after
78
- * the fact) clears a stale registration. Exposed for tests.
206
+ * The step ceiling, or `undefined` to keep the default.
207
+ *
208
+ * A malformed value is ignored rather than thrown on or silently clamped: a
209
+ * typo in an environment variable should leave the ceiling where the code says
210
+ * it is, not quietly become some other number that then gets measured.
79
211
  */
80
- export declare function registerSessionParent(sessionId: unknown, parentId: unknown): void;
81
- /** Test-only: forget every registered session→parent edge. */
82
- export declare function resetSessionParents(): void;
212
+ export declare function maxStepsFromEnv(): number | undefined;
83
213
  /**
84
- * Build the OpenCode plugin function with the same behavior for every host
85
- * entry point (thin generated loaders, direct imports).
86
- *
87
- * State resolution is ALWAYS per-project: the state file path is computed
88
- * from the session cwd on EVERY hook call via
89
- * `resolveStatePathForCwd(process.cwd(), os.homedir(), agentId)` — each
90
- * project gets its own `<cwd>/.skillstate/`, each session (sub-agent) its
91
- * isolated `agents/<session>/` copy, and a session launched from `$HOME`
92
- * uses the global bucket.
214
+ * The plugin definition.
215
+ *
216
+ * `setup` wires the session registry, the project state store, the native
217
+ * tools, the mode resolver and the one `context` hook, then returns a cleanup
218
+ * function.
219
+ *
220
+ * - a {@link SessionRegistry}, fed by the server event stream, so a
221
+ * sub-agent session is recognised and given its own state file;
222
+ * - a {@link ProjectStateStore} rooted at the plugin's own project
223
+ * location, so two checkouts served by one OpenCode server never share
224
+ * state;
225
+ * - a {@link SpecResolver} for paper mode's P, so a project that ships its
226
+ * own `skill-spec.json` gets its own procedure;
227
+ * - a {@link PaperStateSink}, in paper mode only, which applies the
228
+ * `state_patch` the model emits;
229
+ * - native tools plus a single `context` hook whose body depends on the mode.
230
+ *
231
+ * The event subscription is the only resource the plugin owns, so the
232
+ * returned cleanup aborts it. Hook and tool registrations are disposed by
233
+ * OpenCode when the plugin unloads.
93
234
  */
94
- export declare function createSkillStatePlugin(options?: SkillStatePluginOptions): SkillStatePlugin;
235
+ export declare const SkillStatePlugin: Plugin.Plugin;
236
+ export default SkillStatePlugin;
95
237
  //# sourceMappingURL=plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAmCA,OAAO,EAGL,UAAU,EAGV,sBAAsB,EAEvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EACV,eAAe,EAEf,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAE3B,cAAc,mBAAmB,CAAC;AAElC;;;;;;;;GAQG;AACH,OAAO,EAAE,sBAAsB,IAAI,sBAAsB,EAAE,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACtC,0DAA0D;IAC1D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAWtF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYzB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAG7E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,EAC9B,QAAQ,CAAC,EAAE,eAAe,EAAE,GAC3B,MAAM,CAeR;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAUjF;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAgBD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,uBAA4B,GAAG,gBAAgB,CAwG9F"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmFG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAkB1C,mFAAmF;AACnF,eAAO,MAAM,SAAS,eAAe,CAAC;AAEtC;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,aAAa,CAAC;AAqJ1C;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAOxE;AAED;;;;;;;;GAQG;AACH,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG,MAAM,CAUpG;AAUD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,QAAQ,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,EAC3D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,IAAI,CA4BN;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,MAAM,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5G,IAAI,CAON;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,MAAM,EAAE;IACN,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,GACA,IAAI,CAON;AAED;;;;;;GAMG;AAEH,wBAAgB,eAAe,IAAI,MAAM,GAAG,SAAS,CAQpD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,gBAAgB,eAgf3B,CAAC;eAEY,gBAAgB"}