@corenel/web-ui 0.2.0 → 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.
Files changed (50) hide show
  1. package/LICENSE +93 -0
  2. package/dist/AskUser.js +1 -1
  3. package/dist/AskUser.js.map +1 -1
  4. package/dist/CommandTray.d.ts +21 -0
  5. package/dist/CommandTray.d.ts.map +1 -0
  6. package/dist/CommandTray.js +102 -0
  7. package/dist/CommandTray.js.map +1 -0
  8. package/dist/Composer.d.ts +11 -1
  9. package/dist/Composer.d.ts.map +1 -1
  10. package/dist/Composer.js +76 -3
  11. package/dist/Composer.js.map +1 -1
  12. package/dist/ContextBar.d.ts.map +1 -1
  13. package/dist/ContextBar.js +7 -1
  14. package/dist/ContextBar.js.map +1 -1
  15. package/dist/ProcessDock.d.ts +45 -0
  16. package/dist/ProcessDock.d.ts.map +1 -0
  17. package/dist/ProcessDock.js +150 -0
  18. package/dist/ProcessDock.js.map +1 -0
  19. package/dist/TodoBar.d.ts +3 -0
  20. package/dist/TodoBar.d.ts.map +1 -0
  21. package/dist/TodoBar.js +163 -0
  22. package/dist/TodoBar.js.map +1 -0
  23. package/dist/Transcript.js +1 -1
  24. package/dist/Transcript.js.map +1 -1
  25. package/dist/agentChat/AgentChat.d.ts +10 -0
  26. package/dist/agentChat/AgentChat.d.ts.map +1 -1
  27. package/dist/agentChat/AgentChat.js +69 -8
  28. package/dist/agentChat/AgentChat.js.map +1 -1
  29. package/dist/agentChat/OptionsDrawer.js +5 -5
  30. package/dist/agentChat/OptionsDrawer.js.map +1 -1
  31. package/dist/agentChat/controller.d.ts +23 -0
  32. package/dist/agentChat/controller.d.ts.map +1 -1
  33. package/dist/agentChat/controller.js.map +1 -1
  34. package/dist/commandTurn.d.ts +47 -0
  35. package/dist/commandTurn.d.ts.map +1 -0
  36. package/dist/commandTurn.js +64 -0
  37. package/dist/commandTurn.js.map +1 -0
  38. package/dist/composerHistory.d.ts +10 -0
  39. package/dist/composerHistory.d.ts.map +1 -0
  40. package/dist/composerHistory.js +44 -0
  41. package/dist/composerHistory.js.map +1 -0
  42. package/dist/sendLater/SendLater.d.ts +31 -0
  43. package/dist/sendLater/SendLater.d.ts.map +1 -0
  44. package/dist/sendLater/SendLater.js +145 -0
  45. package/dist/sendLater/SendLater.js.map +1 -0
  46. package/dist/sendLater/queue.d.ts +69 -0
  47. package/dist/sendLater/queue.d.ts.map +1 -0
  48. package/dist/sendLater/queue.js +216 -0
  49. package/dist/sendLater/queue.js.map +1 -0
  50. package/package.json +6 -5
@@ -30,6 +30,16 @@ export interface ControllerRecordedEvent {
30
30
  at: number;
31
31
  ev: unknown;
32
32
  }
33
+ /** One step of an agent-maintained task list.
34
+ *
35
+ * OPTIONAL on the state below, because only some engines keep one: a proxied
36
+ * ACP agent reports its plan on the session stream, while our own loop tracks
37
+ * todos through a tool. An engine with no plan simply never sets it. */
38
+ export interface ControllerPlanEntry {
39
+ content: string;
40
+ status: 'pending' | 'in_progress' | 'completed';
41
+ priority?: string;
42
+ }
33
43
  /** What AgentChat renders of a session — structurally satisfied by the engine's
34
44
  * SessionState (extra fields on the real state are fine). */
35
45
  export interface ControllerSessionState {
@@ -43,9 +53,13 @@ export interface ControllerSessionState {
43
53
  mode: string;
44
54
  input: string;
45
55
  attachments: string[];
56
+ /** `requester` says who raised it — the run loop, or a command the user typed.
57
+ * Optional so an engine that only ever asks on the agent's behalf need not
58
+ * set it; absent reads as 'agent'. */
46
59
  pendingPerm: {
47
60
  tool: string;
48
61
  summary: string;
62
+ requester?: 'agent' | 'you';
49
63
  } | null;
50
64
  pendingAsk: {
51
65
  questions: AskQuestion[];
@@ -58,9 +72,18 @@ export interface ControllerSessionState {
58
72
  message: string;
59
73
  action: string;
60
74
  }[];
75
+ /** A console command still running, or null. Optional so a surface whose
76
+ * controller predates it (the ACP chat controller) still satisfies the type
77
+ * rather than being forced to model a command channel it does not have. */
78
+ pendingCommand?: {
79
+ command: string;
80
+ startedAt: number;
81
+ } | null;
61
82
  degradedModel: string | null;
62
83
  /** Raw event stream of the active session, for a host-injected live timeline. */
63
84
  recEvents: ControllerRecordedEvent[];
85
+ /** The agent's current task list, when it publishes one. */
86
+ plan?: ControllerPlanEntry[];
64
87
  }
65
88
  /** Structural view of the multi-session agent engine. @corenel/tools-web's
66
89
  * AgentRuntime satisfies this WITHOUT web-ui importing it (the Phase 3
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../agentChat/controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../agentChat/controller.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../agentChat/controller.ts"],"names":[],"mappings":"AAAA;;;;kCAIkC;AAClC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAwE9C,sFAAsF;AACtF,MAAM,UAAU,oBAAoB,CAAyB,UAAqC,EAAE,EAAU;IAC5G,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,UAAU,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACtD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC9C,KAAK,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;IACrB,OAAO,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,mBAAmB,CAAyB,UAAqC;IAC/F,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,UAAU,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACvD,SAAS,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,CAAC;AACX,CAAC"}
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../agentChat/controller.ts"],"names":[],"mappings":"AAAA;;;;kCAIkC;AAClC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AA4F9C,sFAAsF;AACtF,MAAM,UAAU,oBAAoB,CAAyB,UAAqC,EAAE,EAAU;IAC5G,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,UAAU,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACtD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC9C,KAAK,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;IACrB,OAAO,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,mBAAmB,CAAyB,UAAqC;IAC/F,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,UAAU,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACvD,SAAS,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { ConversationTurn } from '@corenel/harness/conversation';
2
+ /** The name recordCommand writes. Not a general tool: nothing else may claim it. */
3
+ export declare const COMMAND_TOOL = "console_command";
4
+ export interface CommandTurnInfo {
5
+ turnId: string;
6
+ command: string;
7
+ output: string;
8
+ ok: boolean;
9
+ /** Whether the user has promoted it into context (the Keep decision). */
10
+ kept: boolean;
11
+ /** True for a `>!` shell line, which is recorded with its `!` intact. It
12
+ * matters because a shell command has a SECOND representation — the process
13
+ * card — and showing both put three stacked boxes on screen for one
14
+ * keystroke. */
15
+ shell: boolean;
16
+ }
17
+ /**
18
+ * The command a turn records, or null when it is an ordinary turn.
19
+ *
20
+ * Tolerant on the way in: a session log is durable data that may have been
21
+ * written by an older build, so anything malformed reads as "not a command
22
+ * turn" rather than throwing inside a render.
23
+ */
24
+ export declare function readCommandTurn(turn: ConversationTurn): CommandTurnInfo | null;
25
+ /**
26
+ * The command turn the tray should offer, or null.
27
+ *
28
+ * Only the LAST one, and only while it is un-kept — which is the whole of
29
+ * "output evaporates on the next command". A kept command has moved into the
30
+ * transcript and must not also sit in the tray.
31
+ *
32
+ * SHELL LINES ARE SKIPPED ENTIRELY. A `>!` command already has a representation
33
+ * — the process card, which carries its live output, how it ended, and its own
34
+ * Keep. A tray entry beside it was a third box on screen for one keystroke,
35
+ * whose only content was a pointer to the second. Skipped here rather than
36
+ * suppressed at the source, because the turn itself must still be RECORDED: it
37
+ * is what persists the command to the session log and what Up recalls.
38
+ */
39
+ export declare function trayCommand(turns: ConversationTurn[]): CommandTurnInfo | null;
40
+ /**
41
+ * The turns the transcript should render: everything except un-kept commands.
42
+ *
43
+ * An un-kept command is not in context, so showing it in the transcript would
44
+ * claim the agent can see something it cannot.
45
+ */
46
+ export declare function transcriptTurns(turns: ConversationTurn[]): ConversationTurn[];
47
+ //# sourceMappingURL=commandTurn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandTurn.d.ts","sourceRoot":"","sources":["../commandTurn.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,oFAAoF;AACpF,eAAO,MAAM,YAAY,oBAAoB,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;IACZ,yEAAyE;IACzE,IAAI,EAAE,OAAO,CAAC;IACd;;;oBAGgB;IAChB,KAAK,EAAE,OAAO,CAAC;CAChB;AAQD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,eAAe,GAAG,IAAI,CAkB9E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,eAAe,GAAG,IAAI,CAO7E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,gBAAgB,EAAE,CAE7E"}
@@ -0,0 +1,64 @@
1
+ /** The name recordCommand writes. Not a general tool: nothing else may claim it. */
2
+ export const COMMAND_TOOL = 'console_command';
3
+ /** The marker that makes a recorded command line a shell line. Kept in step with
4
+ * the host's SHELL_PREFIX by a test. */
5
+ const SHELL_MARK = '!';
6
+ /**
7
+ * The command a turn records, or null when it is an ordinary turn.
8
+ *
9
+ * Tolerant on the way in: a session log is durable data that may have been
10
+ * written by an older build, so anything malformed reads as "not a command
11
+ * turn" rather than throwing inside a render.
12
+ */
13
+ export function readCommandTurn(turn) {
14
+ const first = turn.messages[0];
15
+ const call = first?.tool_calls?.[0];
16
+ if (call?.function?.name !== COMMAND_TOOL)
17
+ return null;
18
+ let command = '';
19
+ let ok = true;
20
+ try {
21
+ const args = JSON.parse(call.function.arguments || '{}');
22
+ command = typeof args.command === 'string' ? args.command : '';
23
+ // Absent means an older record that predates the flag. Treating that as
24
+ // success is right: a failure was always written into the output text too.
25
+ ok = args.ok !== false;
26
+ }
27
+ catch { /* unparseable arguments: keep the empty command */ }
28
+ const result = turn.messages[1];
29
+ const output = typeof result?.content === 'string' ? result.content : '';
30
+ return { turnId: turn.id, command, output, ok, kept: turn.included, shell: command.startsWith(SHELL_MARK) };
31
+ }
32
+ /**
33
+ * The command turn the tray should offer, or null.
34
+ *
35
+ * Only the LAST one, and only while it is un-kept — which is the whole of
36
+ * "output evaporates on the next command". A kept command has moved into the
37
+ * transcript and must not also sit in the tray.
38
+ *
39
+ * SHELL LINES ARE SKIPPED ENTIRELY. A `>!` command already has a representation
40
+ * — the process card, which carries its live output, how it ended, and its own
41
+ * Keep. A tray entry beside it was a third box on screen for one keystroke,
42
+ * whose only content was a pointer to the second. Skipped here rather than
43
+ * suppressed at the source, because the turn itself must still be RECORDED: it
44
+ * is what persists the command to the session log and what Up recalls.
45
+ */
46
+ export function trayCommand(turns) {
47
+ for (let i = turns.length - 1; i >= 0; i--) {
48
+ const info = readCommandTurn(turns[i]);
49
+ if (!info || info.shell)
50
+ continue;
51
+ return info.kept ? null : info;
52
+ }
53
+ return null;
54
+ }
55
+ /**
56
+ * The turns the transcript should render: everything except un-kept commands.
57
+ *
58
+ * An un-kept command is not in context, so showing it in the transcript would
59
+ * claim the agent can see something it cannot.
60
+ */
61
+ export function transcriptTurns(turns) {
62
+ return turns.filter((t) => t.included || !readCommandTurn(t));
63
+ }
64
+ //# sourceMappingURL=commandTurn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandTurn.js","sourceRoot":"","sources":["../commandTurn.ts"],"names":[],"mappings":"AAWA,oFAAoF;AACpF,MAAM,CAAC,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAgB9C;wCACwC;AACxC,MAAM,UAAU,GAAG,GAAG,CAAC;AAIvB;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,IAAsB;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAA+C,CAAC;IAC7E,MAAM,IAAI,GAAG,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,IAAI,EAAE,QAAQ,EAAE,IAAI,KAAK,YAAY;QAAE,OAAO,IAAI,CAAC;IAEvD,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,EAAE,GAAG,IAAI,CAAC;IACd,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,IAAI,CAAuC,CAAC;QAC/F,OAAO,GAAG,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,wEAAwE;QACxE,2EAA2E;QAC3E,EAAE,GAAG,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC,CAAC,mDAAmD,CAAC,CAAC;IAE/D,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAsC,CAAC;IACrE,MAAM,MAAM,GAAG,OAAO,MAAM,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;AAC9G,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK;YAAE,SAAS;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACjC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAyB;IACvD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ConversationTurn } from '@corenel/harness/conversation';
2
+ /**
3
+ * Everything the composer can recall, oldest first.
4
+ *
5
+ * CONSECUTIVE DUPLICATES COLLAPSE. Running the same command three times in a
6
+ * row is common, and three presses of Up that appear to do nothing reads as a
7
+ * broken key rather than as history.
8
+ */
9
+ export declare function composerHistory(turns: ConversationTurn[]): string[];
10
+ //# sourceMappingURL=composerHistory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composerHistory.d.ts","sourceRoot":"","sources":["../composerHistory.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAyBtE;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,MAAM,EAAE,CAUnE"}
@@ -0,0 +1,44 @@
1
+ import { readCommandTurn } from './commandTurn';
2
+ /** The prefix that makes a line a command. Kept in step with the host's
3
+ * COMMAND_PREFIX by the test that round-trips a recorded command. */
4
+ const COMMAND_PREFIX = '>';
5
+ /** The text of a user message turn, or null if it is not one. */
6
+ function userText(turn) {
7
+ const first = turn.messages[0];
8
+ if (first?.role !== 'user')
9
+ return null;
10
+ if (typeof first.content === 'string')
11
+ return first.content;
12
+ // A multimodal turn is an array of parts; recall the text, since the images
13
+ // cannot be put back in the box anyway.
14
+ if (Array.isArray(first.content)) {
15
+ const text = first.content
16
+ .filter((p) => p?.type === 'text' && typeof p.text === 'string')
17
+ .map((p) => p.text)
18
+ .join('\n')
19
+ .trim();
20
+ return text || null;
21
+ }
22
+ return null;
23
+ }
24
+ /**
25
+ * Everything the composer can recall, oldest first.
26
+ *
27
+ * CONSECUTIVE DUPLICATES COLLAPSE. Running the same command three times in a
28
+ * row is common, and three presses of Up that appear to do nothing reads as a
29
+ * broken key rather than as history.
30
+ */
31
+ export function composerHistory(turns) {
32
+ const out = [];
33
+ for (const turn of turns) {
34
+ const cmd = readCommandTurn(turn);
35
+ const entry = cmd ? `${COMMAND_PREFIX}${cmd.command}` : userText(turn);
36
+ if (!entry)
37
+ continue;
38
+ if (out[out.length - 1] === entry)
39
+ continue;
40
+ out.push(entry);
41
+ }
42
+ return out;
43
+ }
44
+ //# sourceMappingURL=composerHistory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composerHistory.js","sourceRoot":"","sources":["../composerHistory.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD;qEACqE;AACrE,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B,iEAAiE;AACjE,SAAS,QAAQ,CAAC,IAAsB;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAqD,CAAC;IACnF,IAAI,KAAK,EAAE,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IAC5D,4EAA4E;IAC5E,wCAAwC;IACxC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,GAAI,KAAK,CAAC,OAA8C;aAC/D,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;aAC/D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aAClB,IAAI,CAAC,IAAI,CAAC;aACV,IAAI,EAAE,CAAC;QACV,OAAO,IAAI,IAAI,IAAI,CAAC;IACtB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,KAAyB;IACvD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,cAAc,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACvE,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK;YAAE,SAAS;QAC5C,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { type QueuedSend } from './queue';
3
+ /**
4
+ * Runs the queue: ticks, fires what is due, and re-renders on every change.
5
+ *
6
+ * `send` is called with the parked text and must send it exactly as a typed
7
+ * message would be sent. It is held in a ref so a fresh closure each render
8
+ * never restarts the interval.
9
+ *
10
+ * `busy` suppresses firing while a turn is running -- the message stays queued
11
+ * and goes on the next tick instead. Dropping it would lose what the user
12
+ * parked; sending into a running turn is not possible.
13
+ */
14
+ export declare function useSendLater(send: (text: string) => void, busy: boolean): {
15
+ items: QueuedSend[];
16
+ now: number;
17
+ };
18
+ export interface SendLaterProps {
19
+ /** The composer's current text -- what gets parked. */
20
+ text: string;
21
+ /** Clears the composer after parking, so the message is in one place only. */
22
+ onQueued: () => void;
23
+ /** Sends a MISSED message the user chose to release. Same send path as the
24
+ * timer's -- the difference is only who decided. */
25
+ onSendNow: (text: string) => void;
26
+ /** The live queue + clock from useSendLater. */
27
+ items: QueuedSend[];
28
+ now: number;
29
+ }
30
+ export declare function SendLater({ text, onQueued, onSendNow, items, now }: SendLaterProps): React.ReactElement;
31
+ //# sourceMappingURL=SendLater.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SendLater.d.ts","sourceRoot":"","sources":["../../sendLater/SendLater.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAExE,OAAO,EAGyB,KAAK,UAAU,EAC9C,MAAM,SAAS,CAAC;AAajB;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,IAAI,EAAE,OAAO;;;EA4BvE;AAED,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;wDACoD;IACpD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,gDAAgD;IAChD,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,cAAc,GAAG,KAAK,CAAC,YAAY,CAoIvG"}
@@ -0,0 +1,145 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /* The "send later" control, beside Send.
3
+ *
4
+ * A clock button that parks whatever is in the composer and a list of what is
5
+ * already parked, each editable and cancellable. See queue.ts for why this is
6
+ * explicitly not a scheduled task.
7
+ *
8
+ * The firing loop lives here too, in useSendLater, because a timer needs a
9
+ * component's lifetime to be cleaned up and this is the component that is
10
+ * mounted for exactly as long as the chat is.
11
+ */
12
+ import { useCallback, useEffect, useRef, useState } from 'react';
13
+ import { IcClock, IcX, IcCheck } from '@corenel/ui-kit/icons';
14
+ import { PRESETS, HOUR_OPTIONS, queued, queueSend, editQueued, cancelQueued, takeDue, takeOne, requeue, missDuringGap, onQueueChange, formatRemaining, remainingMs, } from './queue';
15
+ /** How often the queue is checked. A minute-resolution feature does not need a
16
+ * tighter loop, and the countdown only renders whole minutes. */
17
+ const TICK_MS = 5000;
18
+ /** A gap longer than this between ticks means the page was not really running --
19
+ * a slept machine, a throttled background tab. Anything that came due inside
20
+ * such a gap is MISSED, not sent, the same as if the tab had been closed:
21
+ * nobody was watching, so nothing sends itself. Generous next to TICK_MS so
22
+ * ordinary scheduler jitter never trips it. */
23
+ const UNWATCHED_GAP_MS = 90000;
24
+ /**
25
+ * Runs the queue: ticks, fires what is due, and re-renders on every change.
26
+ *
27
+ * `send` is called with the parked text and must send it exactly as a typed
28
+ * message would be sent. It is held in a ref so a fresh closure each render
29
+ * never restarts the interval.
30
+ *
31
+ * `busy` suppresses firing while a turn is running -- the message stays queued
32
+ * and goes on the next tick instead. Dropping it would lose what the user
33
+ * parked; sending into a running turn is not possible.
34
+ */
35
+ export function useSendLater(send, busy) {
36
+ const [items, setItems] = useState(() => queued());
37
+ const [now, setNow] = useState(() => Date.now());
38
+ const sendRef = useRef(send);
39
+ sendRef.current = send;
40
+ const busyRef = useRef(busy);
41
+ busyRef.current = busy;
42
+ useEffect(() => onQueueChange(() => setItems(queued())), []);
43
+ const lastTick = useRef(Date.now());
44
+ useEffect(() => {
45
+ const tick = () => {
46
+ const t = Date.now();
47
+ const gap = t - lastTick.current;
48
+ lastTick.current = t;
49
+ setNow(t);
50
+ // Nothing was watching across that gap, so nothing sends itself.
51
+ if (gap > UNWATCHED_GAP_MS) {
52
+ missDuringGap(t);
53
+ return;
54
+ }
55
+ if (busyRef.current)
56
+ return;
57
+ for (const due of takeDue(t))
58
+ sendRef.current(due.text);
59
+ };
60
+ tick();
61
+ const id = setInterval(tick, TICK_MS);
62
+ return () => clearInterval(id);
63
+ }, []);
64
+ return { items, now };
65
+ }
66
+ export function SendLater({ text, onQueued, onSendNow, items, now }) {
67
+ const [open, setOpen] = useState(false);
68
+ const [editing, setEditing] = useState(null);
69
+ const [draft, setDraft] = useState('');
70
+ const [hours, setHours] = useState(HOUR_OPTIONS[0]);
71
+ const wrapRef = useRef(null);
72
+ const canQueue = text.trim().length > 0;
73
+ useEffect(() => {
74
+ if (!open)
75
+ return;
76
+ const onDown = (e) => {
77
+ if (!wrapRef.current?.contains(e.target)) {
78
+ setOpen(false);
79
+ setEditing(null);
80
+ }
81
+ };
82
+ document.addEventListener('mousedown', onDown, true);
83
+ return () => document.removeEventListener('mousedown', onDown, true);
84
+ }, [open]);
85
+ const park = useCallback((minutes) => {
86
+ if (queueSend(text, minutes, Date.now())) {
87
+ onQueued();
88
+ setOpen(false);
89
+ }
90
+ }, [text, onQueued]);
91
+ const commitEdit = (id) => { editQueued(id, { text: draft }); setEditing(null); };
92
+ /* A missed message goes only when the user says so. takeOne removes before
93
+ * sending, like the timer path, so a double click cannot double send. */
94
+ const sendNow = (id) => { const e = takeOne(id); if (e)
95
+ onSendNow(e.text); };
96
+ const missedCount = items.filter((i) => i.missed).length;
97
+ const label = items.length ? String(items.length) : '';
98
+ return (_jsxs("div", { ref: wrapRef, style: S.wrap, children: [_jsxs("button", { style: { ...S.btn, ...(missedCount ? S.btnMissed : items.length ? S.btnActive : null) }, onClick: () => setOpen((o) => !o), title: missedCount
99
+ ? `${missedCount} missed message${missedCount === 1 ? '' : 's'} waiting for you`
100
+ : items.length
101
+ ? `${items.length} message${items.length === 1 ? '' : 's'} queued to send later`
102
+ : 'Send later', "aria-label": "Send later", children: [_jsx(IcClock, { size: 12 }), label && _jsx("span", { style: S.count, children: label })] }), open && (_jsxs("div", { style: S.menu, "data-dock-keepalive": true, children: [_jsx("div", { style: S.head, children: "Send later" }), canQueue ? (_jsxs(_Fragment, { children: [_jsx("div", { style: S.presets, children: PRESETS.map((p) => (_jsx("button", { style: S.preset, onClick: () => park(p.minutes), children: p.label }, p.label))) }), _jsxs("div", { style: S.hourRow, children: [_jsx("select", { style: S.select, value: hours, onChange: (e) => setHours(Number(e.target.value)), "aria-label": "Hours to wait", children: HOUR_OPTIONS.map((h) => _jsxs("option", { value: h, children: [h, " hours"] }, h)) }), _jsx("button", { style: S.hourGo, onClick: () => park(hours * 60), children: "Queue" })] })] })) : (_jsx("div", { style: S.empty, children: "Type a message first \u2014 this parks what is in the composer." })), items.length > 0 && (_jsxs(_Fragment, { children: [_jsx("div", { style: S.divider }), _jsx("div", { style: S.listHead, children: "Queued" }), _jsx("div", { style: S.list, children: items.map((it) => (_jsx("div", { style: S.item, children: editing === it.id ? (_jsxs(_Fragment, { children: [_jsx("textarea", { style: S.editBox, value: draft, autoFocus: true, onChange: (e) => setDraft(e.target.value), onKeyDown: (e) => {
103
+ if (e.key === 'Enter' && !e.shiftKey) {
104
+ e.preventDefault();
105
+ commitEdit(it.id);
106
+ }
107
+ if (e.key === 'Escape') {
108
+ e.preventDefault();
109
+ setEditing(null);
110
+ }
111
+ }, "aria-label": "Edit queued message" }), _jsx("button", { style: S.iconBtn, onClick: () => commitEdit(it.id), title: "Save", "aria-label": "Save", children: _jsx(IcCheck, { size: 12 }) })] })) : (_jsxs(_Fragment, { children: [_jsx("button", { style: S.itemText, title: it.text, onClick: () => { setEditing(it.id); setDraft(it.text); }, children: it.text }), it.missed ? (_jsxs(_Fragment, { children: [_jsx("span", { style: S.missedTag, children: "missed" }), _jsx("button", { style: S.sendNow, onClick: () => sendNow(it.id), title: "Send this now", "aria-label": "Send missed message now", children: "Send" }), _jsx("button", { style: S.iconBtn, onClick: () => requeue(it.id, 30, Date.now()), title: "Wait another 30m", "aria-label": "Re-queue for 30 minutes", children: _jsx(IcClock, { size: 12 }) })] })) : (_jsx("span", { style: S.due, children: formatRemaining(remainingMs(it, now)) })), _jsx("button", { style: S.iconBtn, onClick: () => cancelQueued(it.id), title: "Cancel", "aria-label": "Cancel queued message", children: _jsx(IcX, { size: 12 }) })] })) }, it.id))) }), _jsx("div", { style: S.note, children: missedCount > 0
112
+ ? 'A missed message came due while this tab was closed or asleep. It waits for you rather than sending on its own.'
113
+ : 'Sends from this browser tab while it is open.' })] }))] }))] }));
114
+ }
115
+ const S = {
116
+ wrap: { position: 'relative', display: 'inline-flex' },
117
+ // 34px, matching the stance+Send control beside it -- the two controls sit on
118
+ // the same row and a shorter button reads as an afterthought.
119
+ btn: { display: 'inline-flex', alignItems: 'center', gap: 6, height: 34, padding: '0 12px', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-sm)', background: 'var(--surface-2)', color: 'var(--text-secondary)', fontSize: 12.5, fontWeight: 600, fontFamily: 'inherit', boxShadow: 'var(--shadow-1)', cursor: 'pointer' },
120
+ // Full `border`, not `borderColor`: React warns (correctly) that removing a
121
+ // longhand on rerender while a shorthand is set leads to real styling bugs.
122
+ btnActive: { color: 'var(--accent)', border: '1px solid var(--accent)' },
123
+ btnMissed: { color: 'var(--warn, var(--accent))', border: '1px solid var(--warn, var(--accent))' },
124
+ missedTag: { flex: '0 0 auto', fontSize: 'var(--fs-caption, 11px)', fontWeight: 700, letterSpacing: '0.02em', color: 'var(--warn, var(--accent))' },
125
+ sendNow: { flex: '0 0 auto', height: 22, padding: '0 8px', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-sm)', background: 'var(--surface-2)', color: 'var(--text-secondary)', fontSize: 'var(--fs-caption, 11px)', fontWeight: 700, cursor: 'pointer' },
126
+ count: { fontSize: 12.5, fontWeight: 700, fontVariantNumeric: 'tabular-nums' },
127
+ menu: { position: 'absolute', bottom: 'calc(100% + 6px)', left: 0, zIndex: 'var(--z-dropdown)', width: 300, padding: 8, background: 'var(--surface-1)', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-md)', boxShadow: 'var(--shadow-4, 0 12px 32px rgba(0,0,0,0.4))' },
128
+ head: { fontSize: 'var(--fs-caption, 11px)', fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: 'var(--text-tertiary)', padding: '2px 4px 6px' },
129
+ presets: { display: 'flex', gap: 4 },
130
+ preset: { flex: 1, height: 30, border: '1px solid var(--border-default)', borderRadius: 'var(--radius-sm)', background: 'var(--surface-2)', color: 'var(--text-secondary)', fontWeight: 600, cursor: 'pointer' },
131
+ hourRow: { display: 'flex', gap: 4, marginTop: 6 },
132
+ select: { flex: 1, height: 30, border: '1px solid var(--border-default)', borderRadius: 'var(--radius-sm)', background: 'var(--surface-2)', color: 'var(--text-secondary)', padding: '0 6px' },
133
+ hourGo: { height: 30, padding: '0 10px', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-sm)', background: 'var(--surface-2)', color: 'var(--text-secondary)', fontWeight: 600, cursor: 'pointer' },
134
+ empty: { padding: '4px 4px 2px', color: 'var(--text-tertiary)', fontSize: 'var(--fs-body-sm)' },
135
+ divider: { height: 1, margin: '8px 0', background: 'var(--border-default)' },
136
+ listHead: { fontSize: 'var(--fs-caption, 11px)', fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: 'var(--text-tertiary)', padding: '0 4px 4px' },
137
+ list: { display: 'flex', flexDirection: 'column', gap: 2, maxHeight: 180, overflow: 'auto' },
138
+ item: { display: 'flex', alignItems: 'center', gap: 4, padding: '2px 2px 2px 4px', borderRadius: 'var(--radius-sm)' },
139
+ itemText: { flex: 1, minWidth: 0, border: 'none', background: 'none', padding: 0, color: 'var(--text-secondary)', font: 'inherit', fontSize: 'var(--fs-body-sm)', textAlign: 'left', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', cursor: 'text' },
140
+ editBox: { flex: 1, minWidth: 0, minHeight: 52, resize: 'vertical', border: '1px solid var(--border-default)', borderRadius: 'var(--radius-sm)', background: 'var(--surface-2)', color: 'var(--text-primary)', font: 'inherit', fontSize: 'var(--fs-body-sm)', padding: 4 },
141
+ due: { flex: '0 0 auto', fontSize: 'var(--fs-caption, 11px)', color: 'var(--text-tertiary)', fontVariantNumeric: 'tabular-nums' },
142
+ iconBtn: { flex: '0 0 auto', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 22, height: 22, border: 'none', background: 'none', color: 'var(--text-tertiary)', cursor: 'pointer' },
143
+ note: { padding: '6px 4px 0', color: 'var(--text-tertiary)', fontSize: 'var(--fs-caption, 11px)', lineHeight: 1.4 },
144
+ };
145
+ //# sourceMappingURL=SendLater.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SendLater.js","sourceRoot":"","sources":["../../sendLater/SendLater.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /** One parked message. */
2
+ export interface QueuedSend {
3
+ id: string;
4
+ /** Exactly what will be sent -- the composer's text at queue time, editable after. */
5
+ text: string;
6
+ /** Epoch ms when it should go. */
7
+ dueAt: number;
8
+ /** Epoch ms when it was queued, for "in 20m" vs "queued 20m ago" in the UI. */
9
+ createdAt: number;
10
+ /** Its moment passed while nothing was watching (tab closed, machine asleep).
11
+ * Held rather than sent; the user decides. */
12
+ missed?: boolean;
13
+ }
14
+ /** Presets, in minutes. The dropdown adds longer waits in whole hours. */
15
+ export declare const PRESETS: {
16
+ label: string;
17
+ minutes: number;
18
+ }[];
19
+ /** Longer waits offered in the dropdown, in hours. */
20
+ export declare const HOUR_OPTIONS: number[];
21
+ type Listener = () => void;
22
+ /** Subscribe to queue changes. Returns an unsubscribe. */
23
+ export declare function onQueueChange(l: Listener): () => void;
24
+ /** Everything parked, soonest first. */
25
+ export declare function queued(): QueuedSend[];
26
+ /** Park `text` to be sent in `minutes`. Returns the new entry. */
27
+ export declare function queueSend(text: string, minutes: number, now: number): QueuedSend | null;
28
+ /** Change a parked message's text and/or when it goes. */
29
+ export declare function editQueued(id: string, patch: {
30
+ text?: string;
31
+ dueAt?: number;
32
+ }): void;
33
+ /** Drop a parked message. */
34
+ export declare function cancelQueued(id: string): void;
35
+ /** Drop everything (used by tests and a "clear all" affordance). */
36
+ export declare function clearQueue(): void;
37
+ /**
38
+ * Take everything due at `now` off the queue and return it, soonest first.
39
+ *
40
+ * Removing before sending is deliberate: a message that fires must not be able
41
+ * to fire twice if the send throws, because the user asked for it to be sent
42
+ * once. A failed send surfaces in the transcript like any other failed send.
43
+ */
44
+ export declare function takeDue(now: number): QueuedSend[];
45
+ /**
46
+ * Mark everything that became due during a gap as missed, and return how many.
47
+ *
48
+ * The tab being closed is not the only way a moment passes unwatched -- a
49
+ * sleeping laptop leaves the interval un-run for hours with the page still
50
+ * mounted. Both are the same thing to the person who parked the message, so
51
+ * both get the same answer.
52
+ */
53
+ export declare function missDuringGap(now: number): number;
54
+ /** Take one entry off the queue by id and return it -- the "send it now" path
55
+ * for a missed message. Removed before sending, like takeDue, so one click
56
+ * cannot become two sends. */
57
+ export declare function takeOne(id: string): QueuedSend | null;
58
+ /** Re-arm a missed message for `minutes` from now. */
59
+ export declare function requeue(id: string, minutes: number, now: number): void;
60
+ /** ms until this entry is due; <= 0 means overdue. */
61
+ export declare function remainingMs(entry: QueuedSend, now: number): number;
62
+ /** "5m", "1h 20m", "now" — the countdown shown on a parked message. */
63
+ export declare function formatRemaining(ms: number): string;
64
+ /** Test hook: reset module state so each test starts empty. */
65
+ export declare function resetQueueForTest(): void;
66
+ /** Test hook: reload from storage (proves persistence across a "reload"). */
67
+ export declare function reloadQueueForTest(): void;
68
+ export {};
69
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../sendLater/queue.ts"],"names":[],"mappings":"AAmBA,0BAA0B;AAC1B,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,sFAAsF;IACtF,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB;kDAC8C;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAID,0EAA0E;AAC1E,eAAO,MAAM,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAMvD,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,YAAY,UAA6B,CAAC;AAEvD,KAAK,QAAQ,GAAG,MAAM,IAAI,CAAC;AAmC3B,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,IAAI,CAGrD;AAED,wCAAwC;AACxC,wBAAgB,MAAM,IAAI,UAAU,EAAE,CAErC;AAED,kEAAkE;AAClE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAcvF;AAED,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAerF;AAED,6BAA6B;AAC7B,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAG7C;AAED,oEAAoE;AACpE,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,EAAE,CAOjD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CASjD;AAED;;+BAE+B;AAC/B,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAIrD;AAED,sDAAsD;AACtD,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAStE;AAED,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED,+DAA+D;AAC/D,wBAAgB,iBAAiB,IAAI,IAAI,CAIxC;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}