@guuey/agent-client 0.3.1 → 0.5.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 (47) hide show
  1. package/README.md +54 -7
  2. package/dist/error-codes.d.ts +87 -0
  3. package/dist/error-codes.d.ts.map +1 -0
  4. package/dist/error-codes.js +82 -0
  5. package/dist/errors.d.ts +39 -0
  6. package/dist/errors.d.ts.map +1 -0
  7. package/dist/errors.js +36 -0
  8. package/dist/history.d.ts +1 -1
  9. package/dist/history.d.ts.map +1 -1
  10. package/dist/index.d.ts +13 -7
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +31 -6
  13. package/dist/invoke-turn.d.ts +101 -0
  14. package/dist/invoke-turn.d.ts.map +1 -0
  15. package/dist/invoke-turn.js +124 -0
  16. package/dist/react.d.ts +1 -1
  17. package/dist/react.d.ts.map +1 -1
  18. package/dist/react.js +1 -1
  19. package/dist/saturation-retry.d.ts +101 -0
  20. package/dist/saturation-retry.d.ts.map +1 -0
  21. package/dist/saturation-retry.js +207 -0
  22. package/dist/sse.d.ts +1 -1
  23. package/dist/sse.d.ts.map +1 -1
  24. package/dist/transport.d.ts +90 -0
  25. package/dist/transport.d.ts.map +1 -0
  26. package/dist/transport.js +189 -0
  27. package/dist/types.d.ts +101 -3
  28. package/dist/types.d.ts.map +1 -1
  29. package/dist/useAgentInvoke.d.ts +29 -1
  30. package/dist/useAgentInvoke.d.ts.map +1 -1
  31. package/dist/useAgentInvoke.js +297 -86
  32. package/dist/web-adapters.d.ts +30 -34
  33. package/dist/web-adapters.d.ts.map +1 -1
  34. package/dist/web-adapters.js +72 -123
  35. package/package.json +11 -5
  36. package/src/error-codes.ts +89 -0
  37. package/src/errors.ts +35 -0
  38. package/src/history.ts +1 -1
  39. package/src/index.ts +50 -10
  40. package/src/invoke-turn.ts +187 -0
  41. package/src/react.ts +7 -1
  42. package/src/saturation-retry.ts +247 -0
  43. package/src/sse.ts +1 -1
  44. package/src/transport.ts +260 -0
  45. package/src/types.ts +102 -3
  46. package/src/useAgentInvoke.ts +288 -86
  47. package/src/web-adapters.ts +92 -134
package/README.md CHANGED
@@ -15,12 +15,13 @@ injected as adapters, so the same core runs on web (Next.js) and React Native.
15
15
  npm install @guuey/agent-client
16
16
  ```
17
17
 
18
- ## Two entry points
18
+ ## Three entry points
19
19
 
20
- | Import | Contents | React? |
21
- | --------------------------- | ---------------------------------------------------------------------------------- | ------ |
22
- | `@guuey/agent-client` | SSE helpers, the thread-history reader, `createWebAdapters`, and all public types. | No |
23
- | `@guuey/agent-client/react` | The `useAgentInvoke` hook (+ `applyHistoryResult`). | Yes |
20
+ | Import | Contents | React? |
21
+ | ------------------------------- | ---------------------------------------------------------------------------------------------------- | ------ |
22
+ | `@guuey/agent-client` | SSE helpers, `invokeTurn`, the thread-history reader, `createWebAdapters`, and all public types. | No |
23
+ | `@guuey/agent-client/react` | The `useAgentInvoke` hook (+ `applyHistoryResult`). | Yes |
24
+ | `@guuey/agent-client/transport` | Only the invoke transport + guest-identity pieces — zero `@guuey/mcp-apps-host` in the import graph. | No |
24
25
 
25
26
  The root subpath is React-free — importing it never pulls React in. React is a
26
27
  **required peer** (`react >=18`) because the `./react` subpath needs it; if you
@@ -34,7 +35,11 @@ import { createWebAdapters } from "@guuey/agent-client";
34
35
 
35
36
  export function Chat({ endpointUrl, appId }: { endpointUrl: string; appId: string }) {
36
37
  const adapters = createWebAdapters({ getAccessToken: async () => myToken });
37
- const { messages, send, isStreaming } = useAgentInvoke({ endpointUrl, appId, adapters });
38
+ const { messages, send, status, activeTool, error } = useAgentInvoke({
39
+ endpointUrl,
40
+ appId,
41
+ adapters,
42
+ });
38
43
 
39
44
  return (
40
45
  <>
@@ -43,7 +48,10 @@ export function Chat({ endpointUrl, appId }: { endpointUrl: string; appId: strin
43
48
  {m.text}
44
49
  </p>
45
50
  ))}
46
- <button disabled={isStreaming} onClick={() => send("hello")}>
51
+ {status === "connecting" && <p>Waking your agent…</p>}
52
+ {status === "using-tool" && <p>Using {activeTool}…</p>}
53
+ {error && <p role="alert">{error}</p>}
54
+ <button disabled={status !== "ready"} onClick={() => send("hello")}>
47
55
  Send
48
56
  </button>
49
57
  </>
@@ -51,9 +59,48 @@ export function Chat({ endpointUrl, appId }: { endpointUrl: string; appId: strin
51
59
  }
52
60
  ```
53
61
 
62
+ `status` walks the turn lifecycle — `ready` → `connecting` → `thinking` /
63
+ `using-tool` (with `activeTool` naming the tool) / `responding` → back to
64
+ `ready`. Failures never occupy `status`; they land in `error` and the
65
+ composer re-enables. The full vocabulary is documented at
66
+ [docs.guuey.com/sdk](https://docs.guuey.com/sdk).
67
+
54
68
  On React Native, supply your own adapters (AsyncStorage + an `expo/fetch`
55
69
  transport) in place of `createWebAdapters` — the hook's contract is identical.
56
70
 
71
+ ## Driving a turn without React
72
+
73
+ `invokeTurn` is the same wire walk as the hook, as a pure async generator —
74
+ for a Node harness, a game loop, or any host with its own turn state machine.
75
+ Its event stream is also the observation channel: tool results arrive as
76
+ typed `tool.done` AgEvents, so telemetry is a filter, not a callback API.
77
+
78
+ ```ts
79
+ import { invokeTurn, toInvokeUrl, fetchStreamTransport } from "@guuey/agent-client";
80
+
81
+ const req = {
82
+ url: toInvokeUrl(endpointUrl),
83
+ body: { input, clientMessageId: crypto.randomUUID() },
84
+ signal: controller.signal,
85
+ };
86
+ // `getBearer` is resolved per attempt — a retry re-reads a fresh token.
87
+ const transport = (r) => fetchStreamTransport(r, null, null, { getBearer });
88
+
89
+ for await (const ev of invokeTurn(req, transport)) {
90
+ if (ev.kind !== "message") continue;
91
+ for (const agEvent of ev.agEvents) {
92
+ if (agEvent.type === "tool.done") {
93
+ telemetry.record(agEvent.toolCallId, agEvent.outcome ?? "ok");
94
+ }
95
+ }
96
+ render(ev.assistantText); // full folded text — no delta bookkeeping
97
+ }
98
+ ```
99
+
100
+ The transport retries cold-start 503s (the post-redeploy window) and
101
+ `POD_SATURATED` refusals by itself, never after the first streamed byte;
102
+ tune or disable via its `coldStartRetry` option.
103
+
57
104
  ## React Native / Metro
58
105
 
59
106
  Both entry points declare a `react-native` export condition that points at the
@@ -0,0 +1,87 @@
1
+ /**
2
+ * The pod's error-envelope wire codes, TRANSCRIBED.
3
+ *
4
+ * The source of truth is the runtime's own private module
5
+ * (`backend/services/nocode-runtime/src/error-codes.ts`). This package is
6
+ * published to npm and cannot take a `@guuey-private` dependency, so it keeps
7
+ * its own copy — the same arrangement as {@link GUEST_HEADER} in
8
+ * `./web-adapters.ts` and `@guuey/host`'s mirrored fs-contract constants. The
9
+ * copies are not trusted to prose alone: `agent-client-codes.sync.test.ts` in
10
+ * the runtime package (which can import BOTH) asserts they stay identical, so
11
+ * renaming a code on either side fails that test rather than silently breaking
12
+ * a client branch.
13
+ *
14
+ * WIRE CONTRACT (what these codes appear in):
15
+ *
16
+ * - a pre-stream refusal — `{ "code": …, "message": … }` with an HTTP status,
17
+ * parsed into {@link AgentResponseError};
18
+ * - an in-band failure — `event: error` / `data: { code, message }`, surfaced
19
+ * as `useAgentInvoke`'s `errorCode`.
20
+ *
21
+ * Both channels carry the SAME vocabulary, which is why one mirror serves them.
22
+ */
23
+ export declare const AGENT_ERROR_CODES: {
24
+ /** No usable identity on a surface that requires one. */
25
+ readonly UNAUTHORIZED: "UNAUTHORIZED";
26
+ /** The invoke body did not parse / validate. */
27
+ readonly INVALID_REQUEST: "INVALID_REQUEST";
28
+ /** The builder turned anonymous access off for this agent. */
29
+ readonly GUEST_ACCESS_DISABLED: "GUEST_ACCESS_DISABLED";
30
+ /**
31
+ * The agent's own definition declares `auth: 'required'` and the caller is
32
+ * anonymous — sign in and retry with a bearer. The snapshot-declared twin of
33
+ * {@link AGENT_ERROR_CODES.GUEST_ACCESS_DISABLED} (the app-record runtime
34
+ * override); either gate can refuse.
35
+ */
36
+ readonly AUTH_REQUIRED: "AUTH_REQUIRED";
37
+ /** The caller (or the app) is out of plan allowance — the upgrade prompt. */
38
+ readonly QUOTA_EXCEEDED: "QUOTA_EXCEEDED";
39
+ /** The app hit its builder-set managed spend cap. */
40
+ readonly MANAGED_SPEND_CAP: "MANAGED_SPEND_CAP";
41
+ /**
42
+ * The pod is at its concurrent-turn cap (scaling S1-F3). A 503 carrying a
43
+ * `Retry-After` hint, and the ONE code {@link fetchStreamTransport} retries
44
+ * by itself — see its docblock for the single-attempt rule.
45
+ */
46
+ readonly POD_SATURATED: "POD_SATURATED";
47
+ /**
48
+ * The pod took SIGTERM and refuses NEW turns while in-flight ones finish.
49
+ * Also a 503 + `Retry-After`, but deliberately NOT auto-retried (the
50
+ * endpoint pull re-routes the next request; retrying into the same pod is
51
+ * the one thing guaranteed not to help).
52
+ */
53
+ readonly DRAINING: "DRAINING";
54
+ /** Refused for this caller — e.g. the link-prompt dismiss route's byo-only rule. */
55
+ readonly FORBIDDEN: "FORBIDDEN";
56
+ /** The turn ran past the pod's wall-clock budget. */
57
+ readonly TIMEOUT: "TIMEOUT";
58
+ /** A guuey-side dependency failed (not the agent's own code). */
59
+ readonly PLATFORM_ERROR: "PLATFORM_ERROR";
60
+ /** Unclassified pod failure. */
61
+ readonly INTERNAL: "INTERNAL";
62
+ };
63
+ /** One of the pod's wire codes — see {@link AGENT_ERROR_CODES}. */
64
+ export type AgentErrorCode = (typeof AGENT_ERROR_CODES)[keyof typeof AGENT_ERROR_CODES];
65
+ /**
66
+ * CLIENT-originated failure codes — minted by THIS SDK, never by the pod.
67
+ *
68
+ * Deliberately a SEPARATE constant from {@link AGENT_ERROR_CODES}: that
69
+ * object is a transcribed mirror of the runtime's wire vocabulary, guarded by
70
+ * the runtime-side `agent-client-codes.sync.test.ts` — adding a code the pod
71
+ * never emits there would both break the sync guard and lie about the wire.
72
+ * These codes surface through the SAME `errorCode` channel (it is a plain
73
+ * `string` for exactly this kind of growth), so consumers branch the same
74
+ * way; the split exists so each vocabulary keeps one honest owner.
75
+ */
76
+ export declare const CLIENT_ERROR_CODES: {
77
+ /**
78
+ * The SSE stream went byte-silent mid-turn and bounded history probes never
79
+ * found the finished reply (guuey#192's stall watchdog giving up). The turn
80
+ * is over (`status` returns to `ready`); a retry or a reload may still find
81
+ * the reply if the backend completes later.
82
+ */
83
+ readonly STREAM_STALLED: "STREAM_STALLED";
84
+ };
85
+ /** One of this SDK's client-originated codes — see {@link CLIENT_ERROR_CODES}. */
86
+ export type ClientErrorCode = (typeof CLIENT_ERROR_CODES)[keyof typeof CLIENT_ERROR_CODES];
87
+ //# sourceMappingURL=error-codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,iBAAiB;IAC5B,yDAAyD;;IAEzD,gDAAgD;;IAEhD,8DAA8D;;IAE9D;;;;;OAKG;;IAEH,6EAA6E;;IAE7E,qDAAqD;;IAErD;;;;OAIG;;IAEH;;;;;OAKG;;IAEH,oFAAoF;;IAEpF,qDAAqD;;IAErD,iEAAiE;;IAEjE,gCAAgC;;CAExB,CAAC;AAEX,mEAAmE;AACnE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAExF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB;IAC7B;;;;;OAKG;;CAEK,CAAC;AAEX,kFAAkF;AAClF,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * The pod's error-envelope wire codes, TRANSCRIBED.
3
+ *
4
+ * The source of truth is the runtime's own private module
5
+ * (`backend/services/nocode-runtime/src/error-codes.ts`). This package is
6
+ * published to npm and cannot take a `@guuey-private` dependency, so it keeps
7
+ * its own copy — the same arrangement as {@link GUEST_HEADER} in
8
+ * `./web-adapters.ts` and `@guuey/host`'s mirrored fs-contract constants. The
9
+ * copies are not trusted to prose alone: `agent-client-codes.sync.test.ts` in
10
+ * the runtime package (which can import BOTH) asserts they stay identical, so
11
+ * renaming a code on either side fails that test rather than silently breaking
12
+ * a client branch.
13
+ *
14
+ * WIRE CONTRACT (what these codes appear in):
15
+ *
16
+ * - a pre-stream refusal — `{ "code": …, "message": … }` with an HTTP status,
17
+ * parsed into {@link AgentResponseError};
18
+ * - an in-band failure — `event: error` / `data: { code, message }`, surfaced
19
+ * as `useAgentInvoke`'s `errorCode`.
20
+ *
21
+ * Both channels carry the SAME vocabulary, which is why one mirror serves them.
22
+ */
23
+ export const AGENT_ERROR_CODES = {
24
+ /** No usable identity on a surface that requires one. */
25
+ UNAUTHORIZED: "UNAUTHORIZED",
26
+ /** The invoke body did not parse / validate. */
27
+ INVALID_REQUEST: "INVALID_REQUEST",
28
+ /** The builder turned anonymous access off for this agent. */
29
+ GUEST_ACCESS_DISABLED: "GUEST_ACCESS_DISABLED",
30
+ /**
31
+ * The agent's own definition declares `auth: 'required'` and the caller is
32
+ * anonymous — sign in and retry with a bearer. The snapshot-declared twin of
33
+ * {@link AGENT_ERROR_CODES.GUEST_ACCESS_DISABLED} (the app-record runtime
34
+ * override); either gate can refuse.
35
+ */
36
+ AUTH_REQUIRED: "AUTH_REQUIRED",
37
+ /** The caller (or the app) is out of plan allowance — the upgrade prompt. */
38
+ QUOTA_EXCEEDED: "QUOTA_EXCEEDED",
39
+ /** The app hit its builder-set managed spend cap. */
40
+ MANAGED_SPEND_CAP: "MANAGED_SPEND_CAP",
41
+ /**
42
+ * The pod is at its concurrent-turn cap (scaling S1-F3). A 503 carrying a
43
+ * `Retry-After` hint, and the ONE code {@link fetchStreamTransport} retries
44
+ * by itself — see its docblock for the single-attempt rule.
45
+ */
46
+ POD_SATURATED: "POD_SATURATED",
47
+ /**
48
+ * The pod took SIGTERM and refuses NEW turns while in-flight ones finish.
49
+ * Also a 503 + `Retry-After`, but deliberately NOT auto-retried (the
50
+ * endpoint pull re-routes the next request; retrying into the same pod is
51
+ * the one thing guaranteed not to help).
52
+ */
53
+ DRAINING: "DRAINING",
54
+ /** Refused for this caller — e.g. the link-prompt dismiss route's byo-only rule. */
55
+ FORBIDDEN: "FORBIDDEN",
56
+ /** The turn ran past the pod's wall-clock budget. */
57
+ TIMEOUT: "TIMEOUT",
58
+ /** A guuey-side dependency failed (not the agent's own code). */
59
+ PLATFORM_ERROR: "PLATFORM_ERROR",
60
+ /** Unclassified pod failure. */
61
+ INTERNAL: "INTERNAL",
62
+ };
63
+ /**
64
+ * CLIENT-originated failure codes — minted by THIS SDK, never by the pod.
65
+ *
66
+ * Deliberately a SEPARATE constant from {@link AGENT_ERROR_CODES}: that
67
+ * object is a transcribed mirror of the runtime's wire vocabulary, guarded by
68
+ * the runtime-side `agent-client-codes.sync.test.ts` — adding a code the pod
69
+ * never emits there would both break the sync guard and lie about the wire.
70
+ * These codes surface through the SAME `errorCode` channel (it is a plain
71
+ * `string` for exactly this kind of growth), so consumers branch the same
72
+ * way; the split exists so each vocabulary keeps one honest owner.
73
+ */
74
+ export const CLIENT_ERROR_CODES = {
75
+ /**
76
+ * The SSE stream went byte-silent mid-turn and bounded history probes never
77
+ * found the finished reply (guuey#192's stall watchdog giving up). The turn
78
+ * is over (`status` returns to `ready`); a retry or a reload may still find
79
+ * the reply if the backend completes later.
80
+ */
81
+ STREAM_STALLED: "STREAM_STALLED",
82
+ };
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Error types the transports throw and the hook branches on.
3
+ *
4
+ * Its own module (rather than living in `./web-adapters.ts`) so `useAgentInvoke`
5
+ * — which must stay platform-agnostic — can `instanceof`-narrow a caught error
6
+ * without pulling the web adapter bundle (`fetch`, the history reader,
7
+ * `@guuey/mcp-apps-host`) into a React-Native build.
8
+ */
9
+ /**
10
+ * Thrown when the pod returns a non-2xx status on `/agent/invoke` (before any
11
+ * SSE stream opens). Carries the pod's structured `{ code, message }` when
12
+ * present — e.g. a `QUOTA_EXCEEDED` 429 whose message ("…reached its plan
13
+ * generation limit…") the chat UI should surface — falling back to the bare
14
+ * status for non-JSON failures. See `AGENT_ERROR_CODES` for the vocabulary.
15
+ */
16
+ export declare class AgentResponseError extends Error {
17
+ readonly status: number;
18
+ readonly code?: string | undefined;
19
+ /**
20
+ * The response's `Retry-After` hint in whole seconds, when it sent a
21
+ * parseable one. The pod attaches it to its two 503 refusals
22
+ * (`POD_SATURATED`, `DRAINING`) and exposes the header across origins via
23
+ * `Access-Control-Expose-Headers`, so a browser client can actually read
24
+ * it. `undefined` when the header was absent, malformed, or in the
25
+ * HTTP-date form the pod never emits.
26
+ */
27
+ readonly retryAfterSeconds?: number | undefined;
28
+ constructor(message: string, status: number, code?: string | undefined,
29
+ /**
30
+ * The response's `Retry-After` hint in whole seconds, when it sent a
31
+ * parseable one. The pod attaches it to its two 503 refusals
32
+ * (`POD_SATURATED`, `DRAINING`) and exposes the header across origins via
33
+ * `Access-Control-Expose-Headers`, so a browser client can actually read
34
+ * it. `undefined` when the header was absent, malformed, or in the
35
+ * HTTP-date form the pod never emits.
36
+ */
37
+ retryAfterSeconds?: number | undefined);
38
+ }
39
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM;gBAXnC,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,YAAA;IACtB;;;;;;;OAOG;IACM,iBAAiB,CAAC,EAAE,MAAM,YAAA;CAKtC"}
package/dist/errors.js ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Error types the transports throw and the hook branches on.
3
+ *
4
+ * Its own module (rather than living in `./web-adapters.ts`) so `useAgentInvoke`
5
+ * — which must stay platform-agnostic — can `instanceof`-narrow a caught error
6
+ * without pulling the web adapter bundle (`fetch`, the history reader,
7
+ * `@guuey/mcp-apps-host`) into a React-Native build.
8
+ */
9
+ /**
10
+ * Thrown when the pod returns a non-2xx status on `/agent/invoke` (before any
11
+ * SSE stream opens). Carries the pod's structured `{ code, message }` when
12
+ * present — e.g. a `QUOTA_EXCEEDED` 429 whose message ("…reached its plan
13
+ * generation limit…") the chat UI should surface — falling back to the bare
14
+ * status for non-JSON failures. See `AGENT_ERROR_CODES` for the vocabulary.
15
+ */
16
+ export class AgentResponseError extends Error {
17
+ status;
18
+ code;
19
+ retryAfterSeconds;
20
+ constructor(message, status, code,
21
+ /**
22
+ * The response's `Retry-After` hint in whole seconds, when it sent a
23
+ * parseable one. The pod attaches it to its two 503 refusals
24
+ * (`POD_SATURATED`, `DRAINING`) and exposes the header across origins via
25
+ * `Access-Control-Expose-Headers`, so a browser client can actually read
26
+ * it. `undefined` when the header was absent, malformed, or in the
27
+ * HTTP-date form the pod never emits.
28
+ */
29
+ retryAfterSeconds) {
30
+ super(message);
31
+ this.status = status;
32
+ this.code = code;
33
+ this.retryAfterSeconds = retryAfterSeconds;
34
+ this.name = "AgentResponseError";
35
+ }
36
+ }
package/dist/history.d.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  * has its own copy today and can migrate onto this later.
12
12
  */
13
13
  import type { AgMessage, JsonValue } from "@silverprotocol/core";
14
- import type { AgentMessage, HistoryCard, HistoryLoadResult } from "./types";
14
+ import type { AgentMessage, HistoryCard, HistoryLoadResult } from "./types.js";
15
15
  /** One row of `GET /v1/threads/:id/messages`. */
16
16
  export interface ThreadHistoryRow {
17
17
  seq: number;
@@ -1 +1 @@
1
- {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5E,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CACjC;AAOD;;;;;;;;GAQG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,SAA6B;CAIjD;AAeD,qEAAqE;AACrE,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,YAAY,EAAE,CAOpF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,WAAW,EAAE,CAOhF;AAED,MAAM,WAAW,yBAAyB;IACxC,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,OAAO,EACP,QAAQ,EACR,WAAW,EACX,YAAoB,EACpB,SAAiB,GAClB,EAAE,yBAAyB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAuBxD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAK1E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,EAAE,CAE7E"}
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/E,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CACjC;AAOD;;;;;;;;GAQG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,SAA6B;CAIjD;AAeD,qEAAqE;AACrE,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,YAAY,EAAE,CAOpF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,WAAW,EAAE,CAOhF;AAED,MAAM,WAAW,yBAAyB;IACxC,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,OAAO,EACP,QAAQ,EACR,WAAW,EACX,YAAoB,EACpB,SAAiB,GAClB,EAAE,yBAAyB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAuBxD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAK1E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,EAAE,CAE7E"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,15 @@
1
- export { parseSseEvents, extractAssistantText, reduceAssistantText, stringField, parseConsentRequest, parseLinkRequest, type ParsedSseEvent, } from "./sse";
2
- export { dismissLinkPrompt } from "./link-prompt";
3
- export { createUiResourceReader, type CreateUiResourceReaderOptions, createWebAdapters, localStorageThreadStore, webGenerateId, fetchStreamTransport, AgentResponseError, type CreateWebAdaptersOptions, } from "./web-adapters";
4
- export { fetchThreadHistory, threadHistoryRowsToMessages, threadHistoryRowsToCards, HistoryUnauthorizedError, type ThreadHistoryRow, type ThreadHistoryFetchOptions, } from "./history";
5
- export { ingestMessageFrame } from "./blocks";
6
- export { sortHistoryCards, toolNameFor } from "./history";
1
+ export { parseSseEvents, extractAssistantText, reduceAssistantText, stringField, parseConsentRequest, parseLinkRequest, type ParsedSseEvent, } from "./sse.js";
2
+ export { dismissLinkPrompt } from "./link-prompt.js";
3
+ export { invokeTurn, toInvokeUrl, type InvokeTurnEvent } from "./invoke-turn.js";
4
+ export { createUiActionRelay, type CreateUiActionRelayOptions, createUiResourceReader, type CreateUiResourceReaderOptions, createWebAdapters, localStorageThreadStore, webGenerateId, type CreateWebAdaptersOptions, } from "./web-adapters.js";
5
+ export { fetchStreamTransport, sendableGuestSecret, GUEST_HEADER, withActivityObserver, type FetchStreamTransportOptions, } from "./transport.js";
6
+ export { withSaturationRetry, withColdStartRetry, parseRetryAfterSeconds, type SaturationRetryOptions, type ColdStartRetryOptions, } from "./saturation-retry.js";
7
+ export { AgentResponseError } from "./errors.js";
8
+ export { AGENT_ERROR_CODES, type AgentErrorCode, CLIENT_ERROR_CODES, type ClientErrorCode, } from "./error-codes.js";
9
+ export { fetchThreadHistory, threadHistoryRowsToMessages, threadHistoryRowsToCards, HistoryUnauthorizedError, type ThreadHistoryRow, type ThreadHistoryFetchOptions, } from "./history.js";
10
+ export { ingestMessageFrame } from "./blocks.js";
11
+ export { sortHistoryCards, toolNameFor } from "./history.js";
12
+ export { Reducer } from "@silverprotocol/core";
7
13
  export type { AgEvent, AgReduceResult, AgMessage, AgBlock } from "@silverprotocol/core";
8
- export type { AgentMessage, HistoryCard, ProfileConsentRequest, ProfileLinkRequest, ThreadIdStore, GenerateId, InvokeRequest, InvokeTransport, AgentInvokeAdapters, AgentInvokeHistoryAdapter, AgentInvokeStatus, HistoryLoadResult, UseAgentInvokeOptions, UseAgentInvokeReturn, } from "./types";
14
+ export type { AgentMessage, HistoryCard, ProfileConsentRequest, ProfileLinkRequest, ThreadIdStore, GenerateId, InvokeRequest, InvokeTransport, AgentInvokeAdapters, AgentInvokeHistoryAdapter, AgentInvokeStatus, HistoryLoadResult, StallRecoveryOptions, UseAgentInvokeOptions, UseAgentInvokeReturn, } from "./types.js";
9
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,cAAc,GACpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EACL,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,iBAAiB,EACjB,uBAAuB,EACvB,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,wBAAwB,GAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,GAC/B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAK9C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAI1D,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACxF,YAAY,EACV,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,cAAc,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,EAC/B,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,iBAAiB,EACjB,uBAAuB,EACvB,aAAa,EACb,KAAK,wBAAwB,GAC9B,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,EACpB,KAAK,2BAA2B,GACjC,MAAM,gBAAgB,CAAC;AAOxB,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EACL,iBAAiB,EACjB,KAAK,cAAc,EACnB,kBAAkB,EAClB,KAAK,eAAe,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,GAC/B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAKjD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAM7D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACxF,YAAY,EACV,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,35 @@
1
- export { parseSseEvents, extractAssistantText, reduceAssistantText, stringField, parseConsentRequest, parseLinkRequest, } from "./sse";
2
- export { dismissLinkPrompt } from "./link-prompt";
3
- export { createUiResourceReader, createWebAdapters, localStorageThreadStore, webGenerateId, fetchStreamTransport, AgentResponseError, } from "./web-adapters";
4
- export { fetchThreadHistory, threadHistoryRowsToMessages, threadHistoryRowsToCards, HistoryUnauthorizedError, } from "./history";
5
- export { ingestMessageFrame } from "./blocks";
1
+ export { parseSseEvents, extractAssistantText, reduceAssistantText, stringField, parseConsentRequest, parseLinkRequest, } from "./sse.js";
2
+ export { dismissLinkPrompt } from "./link-prompt.js";
3
+ // One agent turn as a pure async generator the wire walk `useAgentInvoke`
4
+ // wraps, for hosts that drive their own turn state machine (guuey#186 G5).
5
+ export { invokeTurn, toInvokeUrl } from "./invoke-turn.js";
6
+ export { createUiActionRelay, createUiResourceReader, createWebAdapters, localStorageThreadStore, webGenerateId, } from "./web-adapters.js";
7
+ // The invoke transport + guest-identity wire pieces, in their own
8
+ // mcp-apps-host-free module. Consumers that want ONLY this graph (no
9
+ // host-role card layer riding along) import `@guuey/agent-client/transport`
10
+ // instead of the barrel — see that module's docblock (guuey#186 G2).
11
+ export { fetchStreamTransport, sendableGuestSecret, GUEST_HEADER, withActivityObserver, } from "./transport.js";
12
+ // The invoke-refusal retry wrappers, transport-agnostic: a host that brings
13
+ // its own `fetch` (Portal's React-Native transport) wraps them to wear the
14
+ // same semantics as the web transport instead of hand-rolling second copies.
15
+ // `parseRetryAfterSeconds` ships with them because filling
16
+ // `AgentResponseError.retryAfterSeconds` the same way is what makes the
17
+ // wrappers honour the pod's hint.
18
+ export { withSaturationRetry, withColdStartRetry, parseRetryAfterSeconds, } from "./saturation-retry.js";
19
+ export { AgentResponseError } from "./errors.js";
20
+ // The pod's wire-code vocabulary, mirrored — branch on these instead of
21
+ // re-typing the string literals (see the module docblock for the sync guard).
22
+ export { AGENT_ERROR_CODES, CLIENT_ERROR_CODES, } from "./error-codes.js";
23
+ export { fetchThreadHistory, threadHistoryRowsToMessages, threadHistoryRowsToCards, HistoryUnauthorizedError, } from "./history.js";
24
+ export { ingestMessageFrame } from "./blocks.js";
6
25
  // Pure block-walk / resource-narrowing helpers for a block-preserving renderer
7
26
  // (shared by Studio's `AgentBlocks` and Portal-web's agent chat). React-free.
8
27
  // Transcript labeling/ordering helpers (mount narrowing itself moved to
9
28
  // @guuey/mcp-apps-host — the SEP-1865 Host role package; import it directly).
10
- export { sortHistoryCards, toolNameFor } from "./history";
29
+ export { sortHistoryCards, toolNameFor } from "./history.js";
30
+ // Re-export the AgJSON types the block-preserving transcript surfaces, so
31
+ // consumers can name `reduceResult` / block types without a direct
32
+ // `@silverprotocol/core` import — and the `Reducer` CLASS beside them, so a
33
+ // host folding `invokeTurn`'s agEvents outside the hook builds its transcript
34
+ // on the same terms (the types alone forced the direct dep back, guuey#186 G4).
35
+ export { Reducer } from "@silverprotocol/core";
@@ -0,0 +1,101 @@
1
+ /**
2
+ * invokeTurn — one agent turn as a pure async generator (guuey#186 G5).
3
+ *
4
+ * The per-turn loop `useAgentInvoke` runs — SSE accumulate → event switch →
5
+ * cumulative text fold → AgJSON block ingest — used to exist only fused to
6
+ * React state inside the hook, so a host with its own turn state machine
7
+ * (a game loop, a native view model, a server-side driver) had to re-walk
8
+ * the wire switch by hand. This module IS that loop, wire-in / semantics-out
9
+ * and React-free: feed it the request and a transport, iterate
10
+ * {@link InvokeTurnEvent}s. The hook is a thin wrapper that maps each event
11
+ * onto its state setters — behaviour-identical, one walk of the switch,
12
+ * owned here.
13
+ *
14
+ * Turn-scoped by design: the generator owns the CUMULATIVE assistant text
15
+ * for this turn (every `message` event carries the full folded text so far,
16
+ * not a delta). Cross-turn state stays with the caller — notably the AgJSON
17
+ * `Reducer`, which folds an entire conversation: this generator yields each
18
+ * frame's validated `agEvents` and never touches a reducer.
19
+ *
20
+ * Transport failures (e.g. `AgentResponseError` on a pre-stream refusal)
21
+ * propagate out of iteration — catch around the `for await`, exactly as the
22
+ * hook does. Unknown SSE events yield nothing, matching the hook's silent
23
+ * fall-through, so new wire events are additive for every consumer.
24
+ */
25
+ import type { AgEvent } from "@silverprotocol/core";
26
+ import type { AgentInvokeStatus, InvokeRequest, InvokeTransport, ProfileConsentRequest, ProfileLinkRequest } from "./types.js";
27
+ /**
28
+ * One semantic step of a turn. Field conventions:
29
+ *
30
+ * - `message.status` / `message.activeTool` are ABSENT (not null) when the
31
+ * frame implies no change — apply them only when present, so an unknown
32
+ * frame type leaves your state machine untouched (the hook's exact rule:
33
+ * only `tool.start`/`tool.done` ever move `activeTool`, and a text frame
34
+ * moving status to `responding` does NOT clear a lingering tool name).
35
+ * - `message.assistantText` is the full folded text of the turn so far —
36
+ * render it as-is on every event; there is no delta bookkeeping to do.
37
+ * - `message.agEvents` are the frame's validated AgJSON events (empty for
38
+ * bypass frames) — push them into your own cross-turn `Reducer` if you
39
+ * keep a block-preserving transcript, ignore them otherwise.
40
+ */
41
+ export type InvokeTurnEvent = {
42
+ kind: "session";
43
+ threadId: string | null;
44
+ } | {
45
+ kind: "message";
46
+ status?: Extract<AgentInvokeStatus, "thinking" | "using-tool" | "responding">;
47
+ activeTool?: string | null;
48
+ assistantText: string;
49
+ agEvents: AgEvent[];
50
+ } | {
51
+ kind: "error";
52
+ message: string;
53
+ code: string | null;
54
+ } | {
55
+ kind: "profile-consent";
56
+ request: ProfileConsentRequest;
57
+ } | {
58
+ kind: "profile-link";
59
+ request: ProfileLinkRequest;
60
+ } | {
61
+ kind: "done";
62
+ stopReason: string | null;
63
+ };
64
+ /**
65
+ * Normalize an agent endpoint to its invoke URL (guuey#186 G3). Accepts BOTH
66
+ * shapes a consumer legitimately holds — a pod base (`https://host`) and the
67
+ * full invoke URL the deploy-controller records (`https://host/agent/invoke`)
68
+ * — and returns exactly one `/agent/invoke`, trailing slashes dropped. This
69
+ * is the single normalization `useAgentInvoke` applies to its `endpointUrl`;
70
+ * a host driving {@link invokeTurn} (or any raw transport) directly builds
71
+ * its request URL with the same call instead of re-implementing the rule.
72
+ */
73
+ export declare function toInvokeUrl(endpointUrl: string): string;
74
+ /**
75
+ * Drive one `/agent/invoke` turn over `transport`, yielding semantic events.
76
+ * Pure per-turn: no React, no storage, no retry policy (the transport owns
77
+ * saturation retry), no reducer — see the module docblock for what belongs
78
+ * to the caller.
79
+ *
80
+ * The event stream is also the OBSERVATION channel (guuey#186 Gap 4): there
81
+ * is deliberately no `onToolResult` callback API, because filtering the
82
+ * generator expresses it directly — every tool result arrives as a typed
83
+ * `tool.done` AgEvent on a `message` event, carrying `toolCallId`,
84
+ * `content`, `outcome` and `structuredContent`.
85
+ *
86
+ * @example Telemetry off the fold — observe tool results without touching
87
+ * the transcript path:
88
+ * ```ts
89
+ * for await (const ev of invokeTurn(req, transport)) {
90
+ * if (ev.kind !== "message") continue;
91
+ * for (const agEvent of ev.agEvents) {
92
+ * if (agEvent.type === "tool.done") {
93
+ * telemetry.record(agEvent.toolCallId, agEvent.outcome ?? "ok");
94
+ * }
95
+ * }
96
+ * render(ev.assistantText); // the fold is untouched by the observation
97
+ * }
98
+ * ```
99
+ */
100
+ export declare function invokeTurn(req: InvokeRequest, transport: InvokeTransport): AsyncGenerator<InvokeTurnEvent>;
101
+ //# sourceMappingURL=invoke-turn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke-turn.d.ts","sourceRoot":"","sources":["../src/invoke-turn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AASpD,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC5C;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,EAAE,UAAU,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC;IAC9E,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB,GACD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,qBAAqB,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAEhD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAuB,UAAU,CAC/B,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,eAAe,GACzB,cAAc,CAAC,eAAe,CAAC,CA0EjC"}