@qoren/cli 0.1.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 (171) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +162 -0
  3. package/dist/args.d.ts +5 -0
  4. package/dist/args.d.ts.map +1 -0
  5. package/dist/args.js +23 -0
  6. package/dist/args.js.map +1 -0
  7. package/dist/commands/account.d.ts +4 -0
  8. package/dist/commands/account.d.ts.map +1 -0
  9. package/dist/commands/account.js +154 -0
  10. package/dist/commands/account.js.map +1 -0
  11. package/dist/commands/agent.d.ts +27 -0
  12. package/dist/commands/agent.d.ts.map +1 -0
  13. package/dist/commands/agent.js +968 -0
  14. package/dist/commands/agent.js.map +1 -0
  15. package/dist/commands/api.d.ts +4 -0
  16. package/dist/commands/api.d.ts.map +1 -0
  17. package/dist/commands/api.js +66 -0
  18. package/dist/commands/api.js.map +1 -0
  19. package/dist/commands/approvals.d.ts +11 -0
  20. package/dist/commands/approvals.d.ts.map +1 -0
  21. package/dist/commands/approvals.js +140 -0
  22. package/dist/commands/approvals.js.map +1 -0
  23. package/dist/commands/auth.d.ts +4 -0
  24. package/dist/commands/auth.d.ts.map +1 -0
  25. package/dist/commands/auth.js +215 -0
  26. package/dist/commands/auth.js.map +1 -0
  27. package/dist/commands/clients.d.ts +62 -0
  28. package/dist/commands/clients.d.ts.map +1 -0
  29. package/dist/commands/clients.js +311 -0
  30. package/dist/commands/clients.js.map +1 -0
  31. package/dist/commands/console.d.ts +4 -0
  32. package/dist/commands/console.d.ts.map +1 -0
  33. package/dist/commands/console.js +26 -0
  34. package/dist/commands/console.js.map +1 -0
  35. package/dist/commands/customAgent.d.ts +42 -0
  36. package/dist/commands/customAgent.d.ts.map +1 -0
  37. package/dist/commands/customAgent.js +449 -0
  38. package/dist/commands/customAgent.js.map +1 -0
  39. package/dist/commands/designer.d.ts +32 -0
  40. package/dist/commands/designer.d.ts.map +1 -0
  41. package/dist/commands/designer.js +682 -0
  42. package/dist/commands/designer.js.map +1 -0
  43. package/dist/commands/env.d.ts +15 -0
  44. package/dist/commands/env.d.ts.map +1 -0
  45. package/dist/commands/env.js +245 -0
  46. package/dist/commands/env.js.map +1 -0
  47. package/dist/commands/interactive.d.ts +4 -0
  48. package/dist/commands/interactive.d.ts.map +1 -0
  49. package/dist/commands/interactive.js +30 -0
  50. package/dist/commands/interactive.js.map +1 -0
  51. package/dist/commands/jobs.d.ts +4 -0
  52. package/dist/commands/jobs.d.ts.map +1 -0
  53. package/dist/commands/jobs.js +59 -0
  54. package/dist/commands/jobs.js.map +1 -0
  55. package/dist/commands/secrets.d.ts +15 -0
  56. package/dist/commands/secrets.d.ts.map +1 -0
  57. package/dist/commands/secrets.js +164 -0
  58. package/dist/commands/secrets.js.map +1 -0
  59. package/dist/commands/webhook.d.ts +4 -0
  60. package/dist/commands/webhook.d.ts.map +1 -0
  61. package/dist/commands/webhook.js +275 -0
  62. package/dist/commands/webhook.js.map +1 -0
  63. package/dist/config.d.ts +38 -0
  64. package/dist/config.d.ts.map +1 -0
  65. package/dist/config.js +117 -0
  66. package/dist/config.js.map +1 -0
  67. package/dist/context.d.ts +52 -0
  68. package/dist/context.d.ts.map +1 -0
  69. package/dist/context.js +163 -0
  70. package/dist/context.js.map +1 -0
  71. package/dist/duration.d.ts +9 -0
  72. package/dist/duration.d.ts.map +1 -0
  73. package/dist/duration.js +30 -0
  74. package/dist/duration.js.map +1 -0
  75. package/dist/index.d.ts +3 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +27 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/issues.d.ts +10 -0
  80. package/dist/issues.d.ts.map +1 -0
  81. package/dist/issues.js +45 -0
  82. package/dist/issues.js.map +1 -0
  83. package/dist/jobProgress.d.ts +12 -0
  84. package/dist/jobProgress.d.ts.map +1 -0
  85. package/dist/jobProgress.js +56 -0
  86. package/dist/jobProgress.js.map +1 -0
  87. package/dist/loopback.d.ts +28 -0
  88. package/dist/loopback.d.ts.map +1 -0
  89. package/dist/loopback.js +110 -0
  90. package/dist/loopback.js.map +1 -0
  91. package/dist/migrate/apply.d.ts +29 -0
  92. package/dist/migrate/apply.d.ts.map +1 -0
  93. package/dist/migrate/apply.js +135 -0
  94. package/dist/migrate/apply.js.map +1 -0
  95. package/dist/migrate/bundle.d.ts +89 -0
  96. package/dist/migrate/bundle.d.ts.map +1 -0
  97. package/dist/migrate/bundle.js +681 -0
  98. package/dist/migrate/bundle.js.map +1 -0
  99. package/dist/migrate/tar.d.ts +9 -0
  100. package/dist/migrate/tar.d.ts.map +1 -0
  101. package/dist/migrate/tar.js +89 -0
  102. package/dist/migrate/tar.js.map +1 -0
  103. package/dist/output.d.ts +46 -0
  104. package/dist/output.d.ts.map +1 -0
  105. package/dist/output.js +152 -0
  106. package/dist/output.js.map +1 -0
  107. package/dist/program.d.ts +17 -0
  108. package/dist/program.d.ts.map +1 -0
  109. package/dist/program.js +89 -0
  110. package/dist/program.js.map +1 -0
  111. package/dist/runtimes.d.ts +11 -0
  112. package/dist/runtimes.d.ts.map +1 -0
  113. package/dist/runtimes.js +20 -0
  114. package/dist/runtimes.js.map +1 -0
  115. package/dist/slug.d.ts +3 -0
  116. package/dist/slug.d.ts.map +1 -0
  117. package/dist/slug.js +15 -0
  118. package/dist/slug.js.map +1 -0
  119. package/dist/taskChain.d.ts +20 -0
  120. package/dist/taskChain.d.ts.map +1 -0
  121. package/dist/taskChain.js +40 -0
  122. package/dist/taskChain.js.map +1 -0
  123. package/dist/taskDelivery.d.ts +33 -0
  124. package/dist/taskDelivery.d.ts.map +1 -0
  125. package/dist/taskDelivery.js +67 -0
  126. package/dist/taskDelivery.js.map +1 -0
  127. package/dist/tui/app.d.ts +5 -0
  128. package/dist/tui/app.d.ts.map +1 -0
  129. package/dist/tui/app.js +130 -0
  130. package/dist/tui/app.js.map +1 -0
  131. package/dist/tui/index.d.ts +12 -0
  132. package/dist/tui/index.d.ts.map +1 -0
  133. package/dist/tui/index.js +34 -0
  134. package/dist/tui/index.js.map +1 -0
  135. package/dist/tui/model.d.ts +110 -0
  136. package/dist/tui/model.d.ts.map +1 -0
  137. package/dist/tui/model.js +257 -0
  138. package/dist/tui/model.js.map +1 -0
  139. package/dist/tui/overlay.d.ts +66 -0
  140. package/dist/tui/overlay.d.ts.map +1 -0
  141. package/dist/tui/overlay.js +216 -0
  142. package/dist/tui/overlay.js.map +1 -0
  143. package/dist/tui/panes/account.d.ts +5 -0
  144. package/dist/tui/panes/account.d.ts.map +1 -0
  145. package/dist/tui/panes/account.js +108 -0
  146. package/dist/tui/panes/account.js.map +1 -0
  147. package/dist/tui/panes/agents.d.ts +9 -0
  148. package/dist/tui/panes/agents.d.ts.map +1 -0
  149. package/dist/tui/panes/agents.js +340 -0
  150. package/dist/tui/panes/agents.js.map +1 -0
  151. package/dist/tui/panes/chat.d.ts +14 -0
  152. package/dist/tui/panes/chat.d.ts.map +1 -0
  153. package/dist/tui/panes/chat.js +169 -0
  154. package/dist/tui/panes/chat.js.map +1 -0
  155. package/dist/tui/panes/environments.d.ts +6 -0
  156. package/dist/tui/panes/environments.d.ts.map +1 -0
  157. package/dist/tui/panes/environments.js +364 -0
  158. package/dist/tui/panes/environments.js.map +1 -0
  159. package/dist/tui/panes/jobs.d.ts +5 -0
  160. package/dist/tui/panes/jobs.d.ts.map +1 -0
  161. package/dist/tui/panes/jobs.js +104 -0
  162. package/dist/tui/panes/jobs.js.map +1 -0
  163. package/dist/tui/store.d.ts +40 -0
  164. package/dist/tui/store.d.ts.map +1 -0
  165. package/dist/tui/store.js +124 -0
  166. package/dist/tui/store.js.map +1 -0
  167. package/dist/tui/ui.d.ts +95 -0
  168. package/dist/tui/ui.d.ts.map +1 -0
  169. package/dist/tui/ui.js +144 -0
  170. package/dist/tui/ui.js.map +1 -0
  171. package/package.json +51 -0
@@ -0,0 +1,40 @@
1
+ // Task chaining, as typed on the command line.
2
+ //
3
+ // A scheduled task can read the latest output of other tasks of the same
4
+ // agent (or its own previous run) before its prompt on every run. On the
5
+ // command line that is a repeatable `--context-from <task>`, taking a task id,
6
+ // a task name, or "self"; the control plane resolves names and "self" to ids.
7
+ // `--no-context-from` on task-set clears the list.
8
+ /** The control plane refuses more than this many. */
9
+ export const MAX_CONTEXT_FROM = 5;
10
+ export const CONTEXT_FROM_HELP = "read the latest output of another task of this agent before each run: " +
11
+ "a task id, a task name, or \"self\" for this task's own previous run. " +
12
+ `Repeat for more, up to ${MAX_CONTEXT_FROM}`;
13
+ /** Commander collector for the repeatable `--context-from`. */
14
+ export function collectContextFrom(value, previous) {
15
+ return [...(previous ?? []), value];
16
+ }
17
+ /**
18
+ * The `contextFrom` field for a task write. `undefined` (no flag) leaves it
19
+ * out, so a create reads nothing and a replace keeps what it had; `false`
20
+ * (`--no-context-from`) clears it.
21
+ */
22
+ export function resolveContextFrom(option) {
23
+ if (option === undefined)
24
+ return undefined;
25
+ if (option === false)
26
+ return [];
27
+ const refs = option.map((ref) => ref.trim()).filter(Boolean);
28
+ if (refs.length === 0)
29
+ throw new Error("--context-from needs a task id, a task name, or \"self\".");
30
+ if (refs.length > MAX_CONTEXT_FROM)
31
+ throw new Error(`A task can read the output of at most ${MAX_CONTEXT_FROM} tasks.`);
32
+ return refs;
33
+ }
34
+ /** How the task table shows a chain: the names it reads, "self" for its own previous run. */
35
+ export function describeChain(task, tasks) {
36
+ return (task.contextFrom ?? [])
37
+ .map((id) => (id === task.id ? "self" : (tasks.find((t) => t.id === id)?.name ?? id)))
38
+ .join(", ");
39
+ }
40
+ //# sourceMappingURL=taskChain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskChain.js","sourceRoot":"","sources":["../src/taskChain.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,EAAE;AACF,yEAAyE;AACzE,yEAAyE;AACzE,+EAA+E;AAC/E,8EAA8E;AAC9E,mDAAmD;AAEnD,qDAAqD;AACrD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAElC,MAAM,CAAC,MAAM,iBAAiB,GAC5B,wEAAwE;IACxE,wEAAwE;IACxE,0BAA0B,gBAAgB,EAAE,CAAC;AAE/C,+DAA+D;AAC/D,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,QAA8B;IAC9E,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAoC;IACrE,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IACpG,IAAI,IAAI,CAAC,MAAM,GAAG,gBAAgB;QAChC,MAAM,IAAI,KAAK,CAAC,yCAAyC,gBAAgB,SAAS,CAAC,CAAC;IACtF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,aAAa,CAC3B,IAAmD,EACnD,KAA8C;IAE9C,OAAO,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;SAC5B,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;SACrF,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { ScheduledTaskDeliveryPolicy } from "@qoren/sdk";
2
+ export declare const DELIVERY_POLICIES: readonly ScheduledTaskDeliveryPolicy[];
3
+ /**
4
+ * A chat target: `platform`, `platform:chatId` or `platform:chatId:threadId`.
5
+ * Kept in step with the control plane's check (and @qoren/sdk's
6
+ * CHAT_TARGET_PATTERN); copied rather than imported so this CLI still runs
7
+ * against an older published SDK.
8
+ */
9
+ export declare const CHAT_TARGET_RE: RegExp;
10
+ export declare const DELIVERY_HELP = "activity-only, all-channels (every chat channel, Hermes only), or chat (needs --deliver-to)";
11
+ export declare const DELIVER_TO_HELP: string;
12
+ export type DeliveryFields = {
13
+ deliveryPolicy?: ScheduledTaskDeliveryPolicy;
14
+ deliveryTarget?: string | null;
15
+ };
16
+ /**
17
+ * The delivery fields for a task write, from `--delivery` / `--deliver-to`.
18
+ * With neither flag, a create leaves delivery to the server's default and a
19
+ * replace (given the task as it stands) keeps what it had, target included.
20
+ */
21
+ export declare function resolveDelivery(options: {
22
+ delivery?: string;
23
+ deliverTo?: string;
24
+ }, existing?: {
25
+ deliveryPolicy: ScheduledTaskDeliveryPolicy;
26
+ deliveryTarget?: string | null;
27
+ }): DeliveryFields;
28
+ /** How the task table shows delivery: the policy, or the chat it posts to. */
29
+ export declare function describeDelivery(task: {
30
+ deliveryPolicy: string;
31
+ deliveryTarget?: string | null;
32
+ }): string;
33
+ //# sourceMappingURL=taskDelivery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskDelivery.d.ts","sourceRoot":"","sources":["../src/taskDelivery.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,iBAAiB,EAAE,SAAS,2BAA2B,EAInE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QACmD,CAAC;AAE/E,eAAO,MAAM,aAAa,gGACqE,CAAC;AAEhG,eAAO,MAAM,eAAe,QAKmC,CAAC;AAEhE,MAAM,MAAM,cAAc,GAAG;IAC3B,cAAc,CAAC,EAAE,2BAA2B,CAAC;IAC7C,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AASF;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAClD,QAAQ,CAAC,EAAE;IACT,cAAc,EAAE,2BAA2B,CAAC;IAC5C,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,GACA,cAAc,CA2BhB;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,GAAG,MAAM,CAIT"}
@@ -0,0 +1,67 @@
1
+ // Where a scheduled task's results go, as typed on the command line.
2
+ //
3
+ // `--delivery` picks the policy by name; `--deliver-to` names one chat and
4
+ // implies the "chat" policy, which is how an owner points a task at a Telegram
5
+ // group or a Slack channel. The target is checked here with the same pattern
6
+ // the control plane uses, so a typo fails before a request is made, with the
7
+ // accepted forms spelled out, instead of as a bare 400.
8
+ export const DELIVERY_POLICIES = [
9
+ "activity-only",
10
+ "all-channels",
11
+ "chat",
12
+ ];
13
+ /**
14
+ * A chat target: `platform`, `platform:chatId` or `platform:chatId:threadId`.
15
+ * Kept in step with the control plane's check (and @qoren/sdk's
16
+ * CHAT_TARGET_PATTERN); copied rather than imported so this CLI still runs
17
+ * against an older published SDK.
18
+ */
19
+ export const CHAT_TARGET_RE = /^[a-z][a-z0-9_-]{0,31}(:[A-Za-z0-9_@.+-]{1,128}(:[A-Za-z0-9_.-]{1,64})?)?$/;
20
+ export const DELIVERY_HELP = "activity-only, all-channels (every chat channel, Hermes only), or chat (needs --deliver-to)";
21
+ export const DELIVER_TO_HELP = "send each run's result to one chat (sets --delivery chat): " +
22
+ "PLATFORM for that platform's home channel (Hermes only), " +
23
+ "PLATFORM:CHAT_ID for one chat, or PLATFORM:CHAT_ID:THREAD_ID for a thread or topic in it, " +
24
+ "e.g. telegram:-1001234567890, telegram:-1001234567890:42, slack:C0123ABC. " +
25
+ "PLATFORM must be one of the agent's connected chat channels";
26
+ function badTarget(target) {
27
+ return new Error(`"${target}" is not a chat target. Use PLATFORM, PLATFORM:CHAT_ID or PLATFORM:CHAT_ID:THREAD_ID, ` +
28
+ "for example telegram:-1001234567890 or slack:C0123ABC (lowercase platform name, no spaces).");
29
+ }
30
+ /**
31
+ * The delivery fields for a task write, from `--delivery` / `--deliver-to`.
32
+ * With neither flag, a create leaves delivery to the server's default and a
33
+ * replace (given the task as it stands) keeps what it had, target included.
34
+ */
35
+ export function resolveDelivery(options, existing) {
36
+ const { delivery, deliverTo } = options;
37
+ if (delivery !== undefined && !DELIVERY_POLICIES.includes(delivery))
38
+ throw new Error(`--delivery must be one of ${DELIVERY_POLICIES.join(", ")}.`);
39
+ if (deliverTo !== undefined) {
40
+ const target = deliverTo.trim();
41
+ if (!CHAT_TARGET_RE.test(target))
42
+ throw badTarget(deliverTo);
43
+ if (delivery !== undefined && delivery !== "chat")
44
+ throw new Error(`--deliver-to sends to one chat, so it cannot be combined with --delivery ${delivery}.`);
45
+ return { deliveryPolicy: "chat", deliveryTarget: target };
46
+ }
47
+ if (delivery === "chat") {
48
+ if (existing?.deliveryPolicy === "chat" && existing.deliveryTarget)
49
+ return { deliveryPolicy: "chat", deliveryTarget: existing.deliveryTarget };
50
+ throw new Error("--delivery chat needs --deliver-to <target>, for example --deliver-to telegram:-1001234567890.");
51
+ }
52
+ if (delivery !== undefined)
53
+ return { deliveryPolicy: delivery, deliveryTarget: null };
54
+ if (existing)
55
+ return {
56
+ deliveryPolicy: existing.deliveryPolicy,
57
+ deliveryTarget: existing.deliveryPolicy === "chat" ? (existing.deliveryTarget ?? null) : null,
58
+ };
59
+ return {};
60
+ }
61
+ /** How the task table shows delivery: the policy, or the chat it posts to. */
62
+ export function describeDelivery(task) {
63
+ if (task.deliveryPolicy === "chat")
64
+ return task.deliveryTarget ? `chat ${task.deliveryTarget}` : "chat";
65
+ return task.deliveryPolicy;
66
+ }
67
+ //# sourceMappingURL=taskDelivery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskDelivery.js","sourceRoot":"","sources":["../src/taskDelivery.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,2EAA2E;AAC3E,+EAA+E;AAC/E,6EAA6E;AAC7E,6EAA6E;AAC7E,wDAAwD;AAIxD,MAAM,CAAC,MAAM,iBAAiB,GAA2C;IACvE,eAAe;IACf,cAAc;IACd,MAAM;CACP,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GACzB,4EAA4E,CAAC;AAE/E,MAAM,CAAC,MAAM,aAAa,GACxB,6FAA6F,CAAC;AAEhG,MAAM,CAAC,MAAM,eAAe,GAC1B,6DAA6D;IAC7D,2DAA2D;IAC3D,4FAA4F;IAC5F,4EAA4E;IAC5E,6DAA6D,CAAC;AAOhE,SAAS,SAAS,CAAC,MAAc;IAC/B,OAAO,IAAI,KAAK,CACd,IAAI,MAAM,wFAAwF;QAChG,6FAA6F,CAChG,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAkD,EAClD,QAGC;IAED,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IACxC,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,QAAuC,CAAC;QAChG,MAAM,IAAI,KAAK,CAAC,6BAA6B,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEhF,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7D,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,MAAM;YAC/C,MAAM,IAAI,KAAK,CAAC,4EAA4E,QAAQ,GAAG,CAAC,CAAC;QAC3G,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;IAC5D,CAAC;IAED,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,IAAI,QAAQ,EAAE,cAAc,KAAK,MAAM,IAAI,QAAQ,CAAC,cAAc;YAChE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;IACpH,CAAC;IACD,IAAI,QAAQ,KAAK,SAAS;QACxB,OAAO,EAAE,cAAc,EAAE,QAAuC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;IAE3F,IAAI,QAAQ;QACV,OAAO;YACL,cAAc,EAAE,QAAQ,CAAC,cAAc;YACvC,cAAc,EAAE,QAAQ,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;SAC9F,CAAC;IACJ,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,IAGhC;IACC,IAAI,IAAI,CAAC,cAAc,KAAK,MAAM;QAChC,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACtE,OAAO,IAAI,CAAC,cAAc,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Context } from "../context.js";
2
+ export declare function App({ session }: {
3
+ session: Context;
4
+ }): import("react").JSX.Element;
5
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/tui/app.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AA0N7C,wBAAgB,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,+BAQpD"}
@@ -0,0 +1,130 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Box, Text, useApp, useInput, useWindowSize } from "ink";
4
+ import { UiProvider, useUi } from "./overlay.js";
5
+ import { SessionProvider, useSession } from "./store.js";
6
+ import { AccountPane } from "./panes/account.js";
7
+ import { AgentsPane } from "./panes/agents.js";
8
+ import { ChatPane } from "./panes/chat.js";
9
+ import { EnvironmentsPane } from "./panes/environments.js";
10
+ import { JobsPane } from "./panes/jobs.js";
11
+ import { ACCENT } from "./ui.js";
12
+ // The shell: tabs across the top, one pane, one line of hints at the bottom.
13
+ //
14
+ // The keyboard is arbitrated in exactly one place, here, on a rule simple
15
+ // enough to say in a sentence: whoever is deepest has it. An open overlay beats
16
+ // the pane, the chat's message field beats the shell, and everything else falls
17
+ // through to the tab keys. Panes ask for the keyboard by gating their own
18
+ // handlers on the flags this passes down, so there is no hidden precedence to
19
+ // go looking for when a keystroke lands somewhere surprising.
20
+ const TABS = ["environments", "agents", "jobs", "chat", "account"];
21
+ const HELP = `Getting around
22
+
23
+ tab / shift+tab next / previous section
24
+ 1 to 5 jump straight to a section
25
+ up down j k move within a list
26
+ page up/down a screen at a time
27
+ g / G first / last
28
+ enter open what is selected
29
+ r refresh now
30
+ ? this help
31
+ q or ctrl+c quit
32
+
33
+ Environments
34
+ n new R rename s resize c collaboration d destroy a its agents
35
+
36
+ Agents
37
+ n deploy m message R rename x run a command l logs d remove
38
+ f show only one environment's agents enter probe and diagnose
39
+
40
+ Jobs
41
+ enter steps w watch it run c cancel
42
+
43
+ Chat
44
+ a choose an agent enter send esc release the keyboard c clear
45
+
46
+ Everything here goes through the same control plane as the commands, with the
47
+ same credential and the same plan limits. Anything this cannot do yet, the
48
+ commands still can: quit and run "qoren --help".`;
49
+ function Shell() {
50
+ const { profile, profileName } = useSession();
51
+ const ui = useUi();
52
+ const { exit } = useApp();
53
+ const size = useWindowSize();
54
+ const [tab, setTab] = useState("environments");
55
+ const [environmentFilter, setEnvironmentFilter] = useState("");
56
+ const [chatAgent, setChatAgent] = useState(null);
57
+ const [chatTyping, setChatTyping] = useState(true);
58
+ const [reloadKey, setReloadKey] = useState(0);
59
+ // The chat field swallows letters while someone is writing, so the shell's
60
+ // own single-letter keys stand down until escape releases it.
61
+ const captured = tab === "chat" && chatAgent !== null && chatTyping;
62
+ const shellActive = !ui.busy && !captured;
63
+ useInput((input, key) => {
64
+ if (input === "q" || (key.ctrl && input === "c")) {
65
+ exit();
66
+ return;
67
+ }
68
+ if (input === "?") {
69
+ void ui.show("qoren", HELP);
70
+ return;
71
+ }
72
+ if (input === "r") {
73
+ // Remounting the pane is the honest way to refresh everything it
74
+ // holds, including any list it fetched for a picker.
75
+ setReloadKey((n) => n + 1);
76
+ return;
77
+ }
78
+ const index = TABS.indexOf(tab);
79
+ if (key.tab) {
80
+ const step = key.shift ? -1 : 1;
81
+ setTab(TABS[(index + step + TABS.length) % TABS.length] ?? tab);
82
+ return;
83
+ }
84
+ const digit = Number.parseInt(input, 10);
85
+ if (digit >= 1 && digit <= TABS.length) {
86
+ setTab(TABS[digit - 1] ?? tab);
87
+ }
88
+ }, { isActive: shellActive });
89
+ // Ctrl+C has to work even while the chat field has the keyboard: it is the
90
+ // one key nobody should have to press escape first to reach.
91
+ useInput((input, key) => {
92
+ if (key.ctrl && input === "c")
93
+ exit();
94
+ }, { isActive: !shellActive });
95
+ // Two rows of chrome above (title, tabs) and two below (hints, notice), plus
96
+ // the panel's own border and padding.
97
+ const paneHeight = Math.max(4, size.rows - 11);
98
+ const paneWidth = Math.max(40, size.columns - 4);
99
+ const pane = () => {
100
+ switch (tab) {
101
+ case "environments":
102
+ return (_jsx(EnvironmentsPane, { height: paneHeight, focused: !ui.busy, onOpenAgents: (id) => {
103
+ setEnvironmentFilter(id);
104
+ setTab("agents");
105
+ } }, `env-${reloadKey}`));
106
+ case "agents":
107
+ return (_jsx(AgentsPane, { height: paneHeight, focused: !ui.busy, environmentFilter: environmentFilter, onFilterChange: setEnvironmentFilter, onChat: (agent) => {
108
+ setChatAgent(agent);
109
+ setChatTyping(true);
110
+ setTab("chat");
111
+ } }, `agents-${reloadKey}`));
112
+ case "jobs":
113
+ return (_jsx(JobsPane, { height: paneHeight, focused: !ui.busy }, `jobs-${reloadKey}`));
114
+ case "chat":
115
+ return (_jsx(ChatPane, { height: paneHeight, width: paneWidth, focused: !ui.busy, agent: chatAgent, onPickAgent: (agent) => {
116
+ setChatAgent(agent);
117
+ setChatTyping(true);
118
+ }, typing: chatTyping, onTyping: setChatTyping }));
119
+ case "account":
120
+ return (_jsx(AccountPane, { height: paneHeight, focused: !ui.busy }, `account-${reloadKey}`));
121
+ }
122
+ };
123
+ return (_jsxs(Box, { flexDirection: "column", width: size.columns, children: [_jsxs(Box, { justifyContent: "space-between", paddingX: 1, children: [_jsx(Text, { bold: true, color: ACCENT, children: "qoren" }), _jsx(Text, { dimColor: true, children: `${profile.email ?? profileName} ${profile.baseUrl}` })] }), _jsx(Box, { paddingX: 1, children: TABS.map((name, i) => (_jsx(Text, { color: name === tab ? ACCENT : undefined, bold: name === tab, dimColor: name !== tab, children: `${i + 1} ${name} ` }, name))) }), _jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: ui.busy ? "gray" : ACCENT, paddingX: 1, minHeight: paneHeight + 4, children: ui.overlay ?? pane() }), _jsx(Box, { paddingX: 1, children: ui.notice ? (_jsx(Text, { color: ui.notice.tone === "bad" ? "red" : "green", wrap: "truncate-end", children: ui.notice.message })) : (_jsx(Text, { dimColor: true, children: captured
124
+ ? "esc release the keyboard"
125
+ : "tab section r refresh ? help q quit" })) })] }));
126
+ }
127
+ export function App({ session }) {
128
+ return (_jsx(SessionProvider, { value: session, children: _jsx(UiProvider, { children: _jsx(Shell, {}) }) }));
129
+ }
130
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/tui/app.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { Context } from "../context.js";
2
+ export declare class NotATerminal extends Error {
3
+ }
4
+ /**
5
+ * Take over the terminal until the reader quits.
6
+ *
7
+ * Refuses anywhere it cannot work rather than degrading: this needs a keyboard
8
+ * and a screen, and a half-drawn interface in a pipe or a CI log is worse than
9
+ * a sentence saying which command to use instead.
10
+ */
11
+ export declare function runInteractive(session: Context): Promise<void>;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tui/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAQ7C,qBAAa,YAAa,SAAQ,KAAK;CAAG;AAE1C;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBpE"}
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render } from "ink";
3
+ import { App } from "./app.js";
4
+ // Starting interactive mode.
5
+ //
6
+ // Kept apart from the React tree so nothing in src/tui runs on import: the
7
+ // command tree is built for every invocation, including `qoren env ls --json`
8
+ // in a cron job, and mounting a renderer there would be absurd.
9
+ export class NotATerminal extends Error {
10
+ }
11
+ /**
12
+ * Take over the terminal until the reader quits.
13
+ *
14
+ * Refuses anywhere it cannot work rather than degrading: this needs a keyboard
15
+ * and a screen, and a half-drawn interface in a pipe or a CI log is worse than
16
+ * a sentence saying which command to use instead.
17
+ */
18
+ export async function runInteractive(session) {
19
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
20
+ throw new NotATerminal("Interactive mode needs a terminal. Use the commands instead: run `qoren --help`.");
21
+ }
22
+ const instance = render(_jsx(App, { session: session }), {
23
+ // The alternate screen, the way vim and less use it: this gets the whole
24
+ // window, and the reader's scrollback comes back untouched on quit.
25
+ alternateScreen: true,
26
+ // Ctrl+C is wired up in the shell so it can work while the chat field has
27
+ // the keyboard; letting Ink handle it too would be a second exit path with
28
+ // different teardown.
29
+ exitOnCtrlC: false,
30
+ incrementalRendering: true,
31
+ });
32
+ await instance.waitUntilExit();
33
+ }
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tui/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAG/B,6BAA6B;AAC7B,EAAE;AACF,2EAA2E;AAC3E,8EAA8E;AAC9E,gEAAgE;AAEhE,MAAM,OAAO,YAAa,SAAQ,KAAK;CAAG;AAE1C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAgB;IACnD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClD,MAAM,IAAI,YAAY,CACpB,kFAAkF,CACnF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAC,GAAG,IAAC,OAAO,EAAE,OAAO,GAAI,EAAE;QACjD,yEAAyE;QACzE,oEAAoE;QACpE,eAAe,EAAE,IAAI;QACrB,0EAA0E;QAC1E,2EAA2E;QAC3E,sBAAsB;QACtB,WAAW,EAAE,KAAK;QAClB,oBAAoB,EAAE,IAAI;KAC3B,CAAC,CAAC;IAEH,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAC;AACjC,CAAC"}
@@ -0,0 +1,110 @@
1
+ import type { Job } from "@qoren/sdk";
2
+ import { type Tone } from "../output.js";
3
+ /** Ink colour for a lifecycle word. The vocabulary itself lives in output.ts,
4
+ * so the console and the plain tables agree on what "provisioning" means. */
5
+ export declare function toneColor(tone: Tone): string;
6
+ export declare const statusColorName: (status: string) => string;
7
+ /**
8
+ * Move a selection by `delta`, clamped to the list.
9
+ *
10
+ * Clamped rather than wrapping: in a list of thirty environments, holding the
11
+ * down arrow and silently landing back on the first one is disorienting, and
12
+ * there is no way to tell it apart from not having moved at all.
13
+ */
14
+ export declare function moveSelection(count: number, current: number, delta: number): number;
15
+ /**
16
+ * The slice of a list to draw, given how many rows the pane has.
17
+ *
18
+ * The window only moves when the selection would leave it, so paging through a
19
+ * long list scrolls a line at a time instead of jumping by a screenful and
20
+ * losing the reader's place.
21
+ */
22
+ export declare function scrollWindow(count: number, selected: number, height: number, previousStart?: number): {
23
+ start: number;
24
+ end: number;
25
+ };
26
+ export type LineState = {
27
+ value: string;
28
+ cursor: number;
29
+ };
30
+ export declare const emptyLine: (value?: string) => LineState;
31
+ /** The subset of Ink's Key that a text field cares about. */
32
+ export type EditKey = {
33
+ leftArrow?: boolean;
34
+ rightArrow?: boolean;
35
+ backspace?: boolean;
36
+ delete?: boolean;
37
+ home?: boolean;
38
+ end?: boolean;
39
+ ctrl?: boolean;
40
+ meta?: boolean;
41
+ };
42
+ /**
43
+ * Apply one keystroke to a text field.
44
+ *
45
+ * Written as a reducer so the editing rules — including the readline habits
46
+ * people's fingers already know (ctrl+a/e/u/k/w) — can be tested without a
47
+ * terminal. Returns the state unchanged when the keystroke means nothing here.
48
+ *
49
+ * Note on backspace: some terminals report the backspace key as `delete` with
50
+ * no `backspace` flag, so a `delete` at the end of the line rubs out to the
51
+ * left rather than doing nothing at all.
52
+ */
53
+ export declare function editLine(state: LineState, input: string, key: EditKey): LineState;
54
+ export type ChatTurn = {
55
+ /** What the agent has said so far. Grows while the turn streams. */
56
+ text: string;
57
+ /** Still arriving, so the console should keep showing it as in progress. */
58
+ streaming: boolean;
59
+ /** The tool the agent is running right now, when it is running one. */
60
+ tool: string | null;
61
+ /** The conversation to resume next message, when the harness gave one. */
62
+ sessionId: string | null;
63
+ stdErr: string;
64
+ exitCode: number | null;
65
+ };
66
+ /**
67
+ * Read a message job's result.
68
+ *
69
+ * The control plane writes the reply into the job's result as it arrives — a
70
+ * partial snapshot flagged `streaming` a few times a second, then the final
71
+ * one — so polling the job is how the console shows an agent thinking out loud
72
+ * instead of staring at a spinner for two minutes.
73
+ *
74
+ * Read defensively: this is a `Record<string, unknown>` on the wire, and a turn
75
+ * that fell back to the SSH path carries no session id at all.
76
+ */
77
+ export declare function readChatTurn(result: unknown): ChatTurn;
78
+ /**
79
+ * How long to wait before refreshing a pane, in milliseconds.
80
+ *
81
+ * A fleet at rest changes on the scale of minutes and every poll is a real
82
+ * request against someone's control plane, so the idle cadence is deliberately
83
+ * slow. Anything mid-flight — provisioning, deploying, a running job — is worth
84
+ * watching closely, and only then does the console poll hard.
85
+ */
86
+ export declare function refreshDelay(statuses: string[], idleMs?: number, activeMs?: number): number;
87
+ /** Step completion for a job row, e.g. "9/12". Mirrors jobProgress.jobSummary. */
88
+ export declare function jobProgressText(job: Job): string;
89
+ /** The step a job is on right now, for a one-line summary. */
90
+ export declare function currentStep(job: Job): string;
91
+ /**
92
+ * Break text into lines that fit `width`, keeping the newlines it already has.
93
+ *
94
+ * The chat transcript needs to know how many lines a reply actually occupies
95
+ * before it can decide how much of the conversation still fits on screen, and
96
+ * asking the renderer after the fact is too late. Words longer than the width
97
+ * (a URL, a stack frame) are split rather than allowed to overflow.
98
+ */
99
+ export declare function wrapText(text: string, width: number): string[];
100
+ /**
101
+ * A date someone can read, from whatever the wire sent.
102
+ *
103
+ * Timestamps arrive as ISO strings in some places and epoch millis in others
104
+ * (the usage governor's period bounds among them), and "1786150711602" is not
105
+ * an answer to "when does my billing period end".
106
+ */
107
+ export declare function readableDate(value: string | number | null | undefined): string;
108
+ /** Fit text to a column, with an ellipsis when it does not. */
109
+ export declare function truncate(text: string, width: number): string;
110
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/tui/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,cAAc,CAAC;AAUrD;6EAC6E;AAC7E,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAW5C;AAED,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,KAAG,MAClB,CAAC;AAEhC;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,CAGR;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,aAAa,SAAI,GAChB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAOhC;AAID,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,eAAO,MAAM,SAAS,GAAI,cAAU,KAAG,SAGrC,CAAC;AAEH,6DAA6D;AAC7D,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAOF;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,OAAO,GACX,SAAS,CAwDX;AAID,MAAM,MAAM,QAAQ,GAAG;IACrB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAC;IACnB,uEAAuE;IACvE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAaF;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,CAYtD;AAMD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,SAAS,EACf,QAAQ,SAAQ,GACf,MAAM,CAKR;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAIhD;AAED,8DAA8D;AAC9D,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAK5C;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA4B9D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAK9E;AAED,+DAA+D;AAC/D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAI5D"}