@cargo-ai/cli 1.0.78 → 1.0.81

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 (67) hide show
  1. package/README.md +12 -0
  2. package/build/commands/ask/argvFlags.d.ts +18 -0
  3. package/build/commands/ask/argvFlags.d.ts.map +1 -0
  4. package/build/commands/ask/argvFlags.js +46 -0
  5. package/build/commands/ask/artifacts.d.ts +2 -0
  6. package/build/commands/ask/artifacts.d.ts.map +1 -0
  7. package/build/commands/ask/artifacts.js +100 -0
  8. package/build/commands/ask/binding.d.ts +13 -0
  9. package/build/commands/ask/binding.d.ts.map +1 -0
  10. package/build/commands/ask/binding.js +19 -0
  11. package/build/commands/ask/claudeConfig.d.ts +23 -0
  12. package/build/commands/ask/claudeConfig.d.ts.map +1 -0
  13. package/build/commands/ask/claudeConfig.js +33 -0
  14. package/build/commands/ask/completer.d.ts +48 -0
  15. package/build/commands/ask/completer.d.ts.map +1 -0
  16. package/build/commands/ask/completer.js +217 -0
  17. package/build/commands/ask/history.d.ts +32 -0
  18. package/build/commands/ask/history.d.ts.map +1 -0
  19. package/build/commands/ask/history.js +122 -0
  20. package/build/commands/ask/index.d.ts +14 -0
  21. package/build/commands/ask/index.d.ts.map +1 -0
  22. package/build/commands/ask/index.js +111 -0
  23. package/build/commands/ask/localHarness.d.ts +225 -0
  24. package/build/commands/ask/localHarness.d.ts.map +1 -0
  25. package/build/commands/ask/localHarness.js +1074 -0
  26. package/build/commands/ask/messageStream.d.ts +33 -0
  27. package/build/commands/ask/messageStream.d.ts.map +1 -0
  28. package/build/commands/ask/messageStream.js +114 -0
  29. package/build/commands/ask/persist.d.ts +5 -0
  30. package/build/commands/ask/persist.d.ts.map +1 -0
  31. package/build/commands/ask/persist.js +31 -0
  32. package/build/commands/ask/pnpmShim.d.ts +20 -0
  33. package/build/commands/ask/pnpmShim.d.ts.map +1 -0
  34. package/build/commands/ask/pnpmShim.js +39 -0
  35. package/build/commands/ask/prompt.d.ts +20 -0
  36. package/build/commands/ask/prompt.d.ts.map +1 -0
  37. package/build/commands/ask/prompt.js +228 -0
  38. package/build/commands/ask/rewriteChatFlag.d.ts +9 -0
  39. package/build/commands/ask/rewriteChatFlag.d.ts.map +1 -0
  40. package/build/commands/ask/rewriteChatFlag.js +26 -0
  41. package/build/commands/ask/session.d.ts +94 -0
  42. package/build/commands/ask/session.d.ts.map +1 -0
  43. package/build/commands/ask/session.js +965 -0
  44. package/build/commands/ask/slash.d.ts +20 -0
  45. package/build/commands/ask/slash.d.ts.map +1 -0
  46. package/build/commands/ask/slash.js +73 -0
  47. package/build/commands/ask/state.d.ts +9 -0
  48. package/build/commands/ask/state.d.ts.map +1 -0
  49. package/build/commands/ask/state.js +18 -0
  50. package/build/commands/bookDemo.d.ts +14 -0
  51. package/build/commands/bookDemo.d.ts.map +1 -0
  52. package/build/commands/bookDemo.js +100 -0
  53. package/build/commands/runHandler.d.ts +9 -1
  54. package/build/commands/runHandler.d.ts.map +1 -1
  55. package/build/commands/runHandler.js +16 -1
  56. package/build/index.js +56 -18
  57. package/build/paletteLayout.d.ts +6 -1
  58. package/build/paletteLayout.d.ts.map +1 -1
  59. package/build/paletteLayout.js +35 -9
  60. package/build/utils/cdkState.d.ts +17 -4
  61. package/build/utils/cdkState.d.ts.map +1 -1
  62. package/build/utils/cdkState.js +26 -4
  63. package/build/utils/loadCompiledAgent.d.ts.map +1 -1
  64. package/build/utils/loadCompiledAgent.js +51 -11
  65. package/build/utils/prompt.d.ts.map +1 -1
  66. package/build/utils/prompt.js +4 -1
  67. package/package.json +8 -4
@@ -0,0 +1,20 @@
1
+ export type SlashCard = {
2
+ kind: "card";
3
+ text: string;
4
+ };
5
+ export type SlashAction = {
6
+ kind: "action";
7
+ action: "exit" | "new" | "clear" | "pick-agent" | "cancel";
8
+ };
9
+ export type SlashResult = SlashCard | SlashAction;
10
+ /**
11
+ * Parse a user line that starts with `/`. Anything else is prose for the agent.
12
+ *
13
+ * Exported for tests; the ask session is the only production caller.
14
+ */
15
+ export declare function parseSlash(text: string): SlashResult | undefined;
16
+ export declare class ChatSessionAction extends Error {
17
+ readonly action: SlashAction["action"];
18
+ constructor(action: SlashAction["action"]);
19
+ }
20
+ //# sourceMappingURL=slash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slash.d.ts","sourceRoot":"","sources":["../../../src/commands/ask/slash.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,YAAY,GAAG,QAAQ,CAAC;CAC5D,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,WAAW,CAAC;AAmBlD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAqDhE;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;gBAE3B,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;CAK1C"}
@@ -0,0 +1,73 @@
1
+ import { classifySlashToken } from "./completer.js";
2
+ const HELP_TEXT = [
3
+ "Chat commands (these never reach the model):",
4
+ "",
5
+ "/help List these commands",
6
+ "/clear Start a fresh local session (no agent)",
7
+ "/new Same as /clear",
8
+ "/agent Pick a workspace agent, or Local workspace (default)",
9
+ "/cancel Explain how to stop a turn (press Ctrl-C while it runs)",
10
+ "/exit Leave without asking (same as an empty line)",
11
+ "",
12
+ "Ctrl-C stops the turn in flight and brings the prompt back; a chat command",
13
+ "cannot, because the prompt only reads a line between turns.",
14
+ "Default Ask is Claude Code on this machine (--dir / cwd), with no agent.",
15
+ "Slash suggestions and path completion appear as you type. Empty Enter also leaves.",
16
+ "To run a Cargo CLI command, leave Ask and type /orchestration, … in the palette.",
17
+ ].join("\n");
18
+ /**
19
+ * Parse a user line that starts with `/`. Anything else is prose for the agent.
20
+ *
21
+ * Exported for tests; the ask session is the only production caller.
22
+ */
23
+ export function parseSlash(text) {
24
+ const trimmed = text.trim();
25
+ if (trimmed.startsWith("/") === false) {
26
+ return undefined;
27
+ }
28
+ // A cookbook handoff launches Ask with `/cargo-cdk` then a multi-line brief.
29
+ // Chat commands are a single line (`/help`, `/exit`); anything with a
30
+ // newline is prose for the model, including a skill command the harness
31
+ // expands before the first turn.
32
+ if (trimmed.includes("\n") === true) {
33
+ return undefined;
34
+ }
35
+ const [firstWord] = trimmed.split(/\s+/);
36
+ const head = firstWord === undefined ? trimmed : firstWord;
37
+ // A path the completer offered is prose for the model, not a mistyped
38
+ // command — answering `/etc/hosts` with "is not a chat command" would
39
+ // reject its own suggestion. Same classifier as the completer so the two
40
+ // cannot disagree; `/orchestration` and typos come back "unknown" and still
41
+ // get the card below.
42
+ if (classifySlashToken(head) === "path") {
43
+ return undefined;
44
+ }
45
+ const command = head.slice(1).toLowerCase();
46
+ if (command === "help") {
47
+ return { kind: "card", text: HELP_TEXT };
48
+ }
49
+ if (command === "clear" || command === "new") {
50
+ return { kind: "action", action: command === "new" ? "new" : "clear" };
51
+ }
52
+ if (command === "agent") {
53
+ return { kind: "action", action: "pick-agent" };
54
+ }
55
+ if (command === "cancel") {
56
+ return { kind: "action", action: "cancel" };
57
+ }
58
+ if (command === "exit") {
59
+ return { kind: "action", action: "exit" };
60
+ }
61
+ return {
62
+ kind: "card",
63
+ text: `${head} is not a chat command. Run it from the palette as ${head}.`,
64
+ };
65
+ }
66
+ export class ChatSessionAction extends Error {
67
+ action;
68
+ constructor(action) {
69
+ super(`chat-command:${action}`);
70
+ this.name = "ChatSessionAction";
71
+ this.action = action;
72
+ }
73
+ }
@@ -0,0 +1,9 @@
1
+ export declare const ASK_STATE_VERSION = 1;
2
+ export type AskState = {
3
+ version: typeof ASK_STATE_VERSION;
4
+ chatUuid: string;
5
+ agentUuid?: string;
6
+ updatedAt: string;
7
+ };
8
+ export declare function asAskState(value: unknown): AskState | undefined;
9
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/commands/ask/state.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,OAAO,iBAAiB,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CA0B/D"}
@@ -0,0 +1,18 @@
1
+ export const ASK_STATE_VERSION = 1;
2
+ export function asAskState(value) {
3
+ if (value === null || typeof value !== "object") {
4
+ return undefined;
5
+ }
6
+ const { version, chatUuid, agentUuid, updatedAt } = value;
7
+ if (version !== ASK_STATE_VERSION ||
8
+ typeof chatUuid !== "string" ||
9
+ typeof updatedAt !== "string") {
10
+ return undefined;
11
+ }
12
+ return {
13
+ version: ASK_STATE_VERSION,
14
+ chatUuid,
15
+ agentUuid: typeof agentUuid === "string" ? agentUuid : undefined,
16
+ updatedAt,
17
+ };
18
+ }
@@ -0,0 +1,14 @@
1
+ import type { Command } from "commander";
2
+ /**
3
+ * The Cal.com routing form behind "Talk to sales". Same id as
4
+ * `apps/website/src/components/DemoButton/cal.ts`, so a form swap has to
5
+ * update both.
6
+ */
7
+ export declare const SALES_DEMO_FORM_ID = "88911f2a-4d5d-4218-98df-65bcf47bdf8a";
8
+ export declare const SALES_DEMO_URL = "https://cal.com/forms/88911f2a-4d5d-4218-98df-65bcf47bdf8a";
9
+ /**
10
+ * Prefill is allowed only when we have an address; never a guess.
11
+ */
12
+ export declare function bookDemoUrl(email: string | undefined): string;
13
+ export declare function registerBookDemoCommand(program: Command): void;
14
+ //# sourceMappingURL=bookDemo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bookDemo.d.ts","sourceRoot":"","sources":["../../src/commands/bookDemo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,yCAAyC,CAAC;AAEzE,eAAO,MAAM,cAAc,+DAAgD,CAAC;AAE5E;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAM7D;AAOD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6B9D"}
@@ -0,0 +1,100 @@
1
+ import { createApi } from "../api.js";
2
+ import { getConfig } from "../config.js";
3
+ import { openBrowser } from "../utils/openBrowser.js";
4
+ import { colors, info, outputJson } from "./runHandler.js";
5
+ /**
6
+ * The Cal.com routing form behind "Talk to sales". Same id as
7
+ * `apps/website/src/components/DemoButton/cal.ts`, so a form swap has to
8
+ * update both.
9
+ */
10
+ export const SALES_DEMO_FORM_ID = "88911f2a-4d5d-4218-98df-65bcf47bdf8a";
11
+ export const SALES_DEMO_URL = `https://cal.com/forms/${SALES_DEMO_FORM_ID}`;
12
+ /**
13
+ * Prefill is allowed only when we have an address; never a guess.
14
+ */
15
+ export function bookDemoUrl(email) {
16
+ if (email === undefined) {
17
+ return SALES_DEMO_URL;
18
+ }
19
+ return `${SALES_DEMO_URL}?email=${encodeURIComponent(email)}`;
20
+ }
21
+ export function registerBookDemoCommand(program) {
22
+ program
23
+ .command("book-demo")
24
+ .description("Open the calendar to book a Cargo demo with sales")
25
+ .option("--email <email>", "Work email to prefill the calendar form; omit to use the signed-in account")
26
+ .option("--no-open", "Print the URL without launching a browser")
27
+ .addHelpText("after", `
28
+ Prints the same Cal.com form the website's "Talk to sales" button opens, and
29
+ opens it in a browser when one is available. A person still has to pick a time;
30
+ this command does not create a booking.
31
+
32
+ This is not the guided product tour. That is \`cargo-ai start --continue demo\`.
33
+
34
+ When you are signed in, the form is prefilled with your account email unless
35
+ you pass --email.
36
+
37
+ Examples:
38
+ $ cargo-ai book-demo
39
+ $ cargo-ai book-demo --email you@company.com
40
+ $ cargo-ai book-demo --no-open`)
41
+ .action(async (opts) => {
42
+ await runBookDemo(opts);
43
+ });
44
+ }
45
+ async function runBookDemo(opts) {
46
+ const email = await resolveEmail(opts.email);
47
+ const url = bookDemoUrl(email);
48
+ const opened = opts.open === true;
49
+ info("");
50
+ info("To book a demo, open this URL in a browser:");
51
+ info(` ${colors.cyan(url)}`);
52
+ info("");
53
+ info("A person has to pick a time; this command does not create a booking.");
54
+ info("");
55
+ if (opened === true) {
56
+ openBrowser(url);
57
+ }
58
+ outputJson({
59
+ ok: true,
60
+ url,
61
+ opened,
62
+ email,
63
+ note: "A person has to pick a time; this command does not create a booking.",
64
+ });
65
+ }
66
+ async function resolveEmail(flagged) {
67
+ const fromFlag = normalizeEmail(flagged);
68
+ if (fromFlag !== undefined) {
69
+ return fromFlag;
70
+ }
71
+ return signedInEmail();
72
+ }
73
+ function normalizeEmail(value) {
74
+ if (value === undefined) {
75
+ return undefined;
76
+ }
77
+ const trimmed = value.trim();
78
+ if (trimmed === "") {
79
+ return undefined;
80
+ }
81
+ return trimmed;
82
+ }
83
+ /**
84
+ * Best-effort prefill from the signed-in account. Booking does not depend on
85
+ * it, so a missing credential or a failing API call is not an error.
86
+ */
87
+ async function signedInEmail() {
88
+ const { baseUrl, getAccessToken, workspaceUuid } = getConfig();
89
+ if (getAccessToken === undefined) {
90
+ return undefined;
91
+ }
92
+ try {
93
+ const api = createApi({ baseUrl, getAccessToken, workspaceUuid });
94
+ const { user } = await api.userManagement.user.getCurrent();
95
+ return normalizeEmail(user.email);
96
+ }
97
+ catch {
98
+ return undefined;
99
+ }
100
+ }
@@ -47,6 +47,14 @@ type HandleApiCallOpts = {
47
47
  };
48
48
  export declare function handleApiCall<T>(fn: () => Promise<T>, opts?: HandleApiCallOpts): Promise<T>;
49
49
  export declare function sleep(ms: number): Promise<void>;
50
- export declare function pollUntilFinished<T>(getResult: () => Promise<T>, getFinishedAt: (result: T) => Date | string | null | undefined, intervalMs: number): Promise<T>;
50
+ /**
51
+ * Poll until the thing reports a `finishedAt`.
52
+ *
53
+ * `timeoutMs` is opt-in: a run or batch is allowed to take as long as it
54
+ * takes, and a caller watching one interactively can see that it is still
55
+ * going. Pass it where nobody is watching — a non-interactive turn that never
56
+ * finishes would otherwise wait forever in a pipe or a CI job.
57
+ */
58
+ export declare function pollUntilFinished<T>(getResult: () => Promise<T>, getFinishedAt: (result: T) => Date | string | null | undefined, intervalMs: number, timeoutMs?: number): Promise<T>;
51
59
  export {};
52
60
  //# sourceMappingURL=runHandler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runHandler.d.ts","sourceRoot":"","sources":["../../src/commands/runHandler.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS;;;;;;;CAOZ,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAclE,eAAO,MAAM,MAAM;aACR,MAAM,KAAG,MAAM;eACb,MAAM,KAAG,MAAM;gBACd,MAAM,KAAG,MAAM;cACjB,MAAM,KAAG,MAAM;aAChB,MAAM,KAAG,MAAM;cACd,MAAM,KAAG,MAAM;CAC1B,CAAC;AAEF,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAM/C;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAID,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUhE;AAED,KAAK,YAAY,GAAG;IAClB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC,CAAC;AAEF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,KAAK,CAgCpE;AAKD,MAAM,MAAM,OAAO,GAAG;IAEpB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAGlC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAIF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAuBrD;AAkDD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,GAAG,CAQhE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAQ1E;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,OAAO,EAAE,CAAC,EAAE,EACZ,KAAK,EAAE,MAAM,GACZ;IAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IAAC,YAAY,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CASxD;AAKD,KAAK,iBAAiB,GAAG;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACzB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,wBAAsB,aAAa,CAAC,CAAC,EACnC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,CAAC,EAAE,iBAAiB,GACvB,OAAO,CAAC,CAAC,CAAC,CAgEZ;AA0ED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,aAAa,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EAC9D,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,CAAC,CAaZ"}
1
+ {"version":3,"file":"runHandler.d.ts","sourceRoot":"","sources":["../../src/commands/runHandler.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS;;;;;;;CAOZ,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAclE,eAAO,MAAM,MAAM;aACR,MAAM,KAAG,MAAM;eACb,MAAM,KAAG,MAAM;gBACd,MAAM,KAAG,MAAM;cACjB,MAAM,KAAG,MAAM;aAChB,MAAM,KAAG,MAAM;cACd,MAAM,KAAG,MAAM;CAC1B,CAAC;AAEF,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAM/C;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAID,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUhE;AAED,KAAK,YAAY,GAAG;IAClB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC,CAAC;AAEF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,KAAK,CAgCpE;AAKD,MAAM,MAAM,OAAO,GAAG;IAEpB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAGlC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAIF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAuBrD;AAkDD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,GAAG,CAQhE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAQ1E;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,OAAO,EAAE,CAAC,EAAE,EACZ,KAAK,EAAE,MAAM,GACZ;IAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IAAC,YAAY,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CASxD;AAKD,KAAK,iBAAiB,GAAG;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACzB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,wBAAsB,aAAa,CAAC,CAAC,EACnC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,CAAC,EAAE,iBAAiB,GACvB,OAAO,CAAC,CAAC,CAAC,CAgEZ;AA0ED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,aAAa,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EAC9D,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,CAAC,CAyBZ"}
@@ -290,13 +290,28 @@ function extractApiErrorDetail(body) {
290
290
  export function sleep(ms) {
291
291
  return new Promise((resolve) => setTimeout(resolve, ms));
292
292
  }
293
- export async function pollUntilFinished(getResult, getFinishedAt, intervalMs) {
293
+ /**
294
+ * Poll until the thing reports a `finishedAt`.
295
+ *
296
+ * `timeoutMs` is opt-in: a run or batch is allowed to take as long as it
297
+ * takes, and a caller watching one interactively can see that it is still
298
+ * going. Pass it where nobody is watching — a non-interactive turn that never
299
+ * finishes would otherwise wait forever in a pipe or a CI job.
300
+ */
301
+ export async function pollUntilFinished(getResult, getFinishedAt, intervalMs, timeoutMs) {
302
+ const startedAt = Date.now();
294
303
  let result = await handleApiCall(getResult, { spinner: false });
295
304
  while (true) {
296
305
  const finishedAt = getFinishedAt(result);
297
306
  if (finishedAt !== null && finishedAt !== undefined) {
298
307
  return result;
299
308
  }
309
+ if (timeoutMs !== undefined && Date.now() - startedAt >= timeoutMs) {
310
+ const waited = timeoutMs >= 120_000
311
+ ? `${String(Math.round(timeoutMs / 60_000))} minutes`
312
+ : `${String(Math.max(1, Math.round(timeoutMs / 1000)))}s`;
313
+ failWith(`Gave up waiting after ${waited}. It had not finished and may still be running.`);
314
+ }
300
315
  await sleep(intervalMs);
301
316
  result = await handleApiCall(getResult, { spinner: false });
302
317
  }
package/build/index.js CHANGED
@@ -1,12 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
- import { availableCodingAgents, BRAND, canRunPalette, cdkProjectDir, cdkProjectRoot, declareSources, fetchCreditsLeft, fetchWorkspaceName, formatWorkspaceSuffix, isInteractive, printSetupIssues, registerCommands as registerCdkCommands, runPalette, SessionExpiredError, } from "@cargo-ai/cdk/cli";
3
+ import { availableCodingAgents, BRAND, canRunPalette, cdkProjectDir, cdkProjectRoot, creditsLeftOf, declareSources, fetchSubscription, fetchWorkspaceName, formatWorkspaceSuffix, isInteractive, isUnpaidPlan, printSetupIssues, registerCommands as registerCdkCommands, runPalette, SessionExpiredError, } from "@cargo-ai/cdk/cli";
4
4
  import { Command } from "commander";
5
5
  import { AGENT_SKILLS_HINT } from "./agentSkills.js";
6
6
  import { createApi } from "./api.js";
7
7
  import { registerAiCommands } from "./commands/ai/index.js";
8
+ import { pinAskBooleanFlags } from "./commands/ask/argvFlags.js";
9
+ import { registerAskCommand } from "./commands/ask/index.js";
10
+ import { rewriteChatFlag } from "./commands/ask/rewriteChatFlag.js";
8
11
  import { registerAuthCommands } from "./commands/auth/index.js";
9
12
  import { registerBillingCommands } from "./commands/billing/index.js";
13
+ import { registerBookDemoCommand } from "./commands/bookDemo.js";
10
14
  import { registerConnectionCommands } from "./commands/connection/index.js";
11
15
  import { registerContentCommands } from "./commands/content/index.js";
12
16
  import { registerContextCommands } from "./commands/context/index.js";
@@ -62,6 +66,15 @@ Authentication:
62
66
  Use env variables: CARGO_API_TOKEN, CARGO_WORKSPACE_UUID, CARGO_BASE_URL
63
67
  Check status: cargo-ai whoami
64
68
 
69
+ Ask:
70
+ cargo-ai ask "…" Ask in the palette tree, with a first message
71
+ cargo-ai ask --continue Continue the last chat
72
+ cargo-ai ask --print "…" One turn, JSON on stdout
73
+ cargo-ai --chat Open Ask instead of the palette
74
+
75
+ Talk to sales:
76
+ cargo-ai book-demo Open the calendar to book a demo (a person still picks a time)
77
+
65
78
  All commands output JSON to stdout. Status messages, prompts, and errors go to stderr.
66
79
 
67
80
  Exit codes:
@@ -85,6 +98,8 @@ const SETUP_HEADER_SKIP = [
85
98
  "doctor",
86
99
  "version",
87
100
  "mcp",
101
+ "ask",
102
+ "book-demo",
88
103
  ];
89
104
  /**
90
105
  * Say what is wrong before the command runs rather than after it fails, and
@@ -205,14 +220,17 @@ declareSources({
205
220
  },
206
221
  ],
207
222
  });
223
+ const argv = pinAskBooleanFlags(rewriteChatFlag(process.argv));
208
224
  const binPath = process.argv[1] === undefined ? "cargo-ai" : process.argv[1];
209
225
  // First, so it is the first row of the palette: for someone signed in, this is
210
226
  // the shortest path to a briefed coding agent, and it was previously reachable
211
227
  // only by knowing the name of a command that sounds like a one-time thing.
212
228
  registerStartCommand(program, getApi, { binPath, openPalette });
229
+ registerAskCommand(program, getApi, { openPalette });
213
230
  registerAuthCommands(program, getApi);
214
231
  registerVersionCommand(program, version);
215
232
  registerDoctorCommand(program, version);
233
+ registerBookDemoCommand(program);
216
234
  registerObservabilityCommands(program, getApi);
217
235
  registerOrchestrationCommands(program, getApi);
218
236
  registerWorkspaceManagementCommands(program, getApi);
@@ -236,7 +254,7 @@ registerCdkCommands(program
236
254
  // Bare `cargo-ai` in a terminal opens the palette instead of printing the help
237
255
  // wall: twenty command groups is a list to navigate, not one to read. Anything
238
256
  // non-interactive (a pipe, CI, an agent) keeps the help it has always had.
239
- const bare = process.argv.slice(2).length === 0 && canRunPalette();
257
+ const bare = argv.slice(2).length === 0 && canRunPalette();
240
258
  // ...except for someone who has never signed in, for whom that palette is
241
259
  // twenty groups that all exit 3. They get the entrance instead, once.
242
260
  const entrance = bare === true &&
@@ -246,13 +264,13 @@ const entrance = bare === true &&
246
264
  ranBefore: loadStartState() !== undefined,
247
265
  });
248
266
  const start = bare === false
249
- ? program.parseAsync()
267
+ ? program.parseAsync(argv)
250
268
  : entrance === true
251
269
  ? runStart(getApi, { binPath, openPalette }, {})
252
270
  : openPalette();
253
271
  async function openPalette(startPath) {
254
- const [title, latestVersion] = await Promise.all([
255
- paletteTitle(),
272
+ const [chrome, latestVersion] = await Promise.all([
273
+ paletteChrome(),
256
274
  maybeRefreshUpdateCache(),
257
275
  ]);
258
276
  // Probed once: this shells out to `which` per candidate agent, and nobody
@@ -262,7 +280,7 @@ async function openPalette(startPath) {
262
280
  // Re-read after each command: signing in or out from inside the palette
263
281
  // changes both what the setup line says and which rows are worth pinning.
264
282
  // The cwd is re-tested too — a command can create a project in it.
265
- const rebuildLayout = () => {
283
+ const layoutFor = (unpaidPlan) => {
266
284
  // Read once: a layout describing two different directories could offer to
267
285
  // deploy one and name the other.
268
286
  const cwd = process.cwd();
@@ -277,36 +295,56 @@ async function openPalette(startPath) {
277
295
  // undefined, and `deploy` would fall back to the root it must not use.
278
296
  cdkProjectDir: root === undefined ? undefined : cdkProjectDir(root),
279
297
  cwd,
298
+ unpaidPlan,
280
299
  });
281
300
  };
282
301
  await runPalette({
283
302
  program,
284
303
  binPath,
285
304
  startPath,
286
- title,
305
+ title: chrome.title,
287
306
  issues: collectIssues(),
288
307
  refreshIssues: collectIssues,
289
- layout: rebuildLayout(),
290
- refreshLayout: rebuildLayout,
308
+ // First paint reuses the subscription already fetched for the title.
309
+ layout: layoutFor(chrome.unpaidPlan),
310
+ // After a command the plan can change (sign-in, upgrade); look it up again.
311
+ refreshLayout: async () => layoutFor(await resolveUnpaidPlan()),
291
312
  });
292
313
  }
293
314
  /**
294
- * `🧱 cargo-ai 1.0.66 · Acme · 9,657.48 credits`. The two lookups behind the
295
- * second half are the same best-effort, time-boxed ones `cargo-cdk` uses, so a
296
- * bare invocation still opens promptly when the network does not answer — and
297
- * they are skipped entirely when there is no credential to make them with.
315
+ * `🧱 cargo-ai 1.0.66 · Acme · 9,657.48 credits`, plus whether the workspace
316
+ * is unpaid so the first palette paint can pin Book a demo without a second
317
+ * billing round-trip. Skipped entirely when there is no credential.
298
318
  */
299
- async function paletteTitle() {
319
+ async function paletteChrome() {
300
320
  const base = `${BRAND} cargo-ai ${version}`;
301
321
  if (isSignedIn() === false) {
302
- return base;
322
+ return { title: base, unpaidPlan: false };
303
323
  }
304
324
  const api = getApi();
305
- const [name, creditsLeft] = await Promise.all([
325
+ const [name, subscription] = await Promise.all([
306
326
  fetchWorkspaceName(api),
307
- fetchCreditsLeft(api),
327
+ fetchSubscription(api),
308
328
  ]);
309
- return `${base}${formatWorkspaceSuffix(name, creditsLeft)}`;
329
+ const creditsLeft = subscription === undefined ? undefined : creditsLeftOf(subscription);
330
+ return {
331
+ title: `${base}${formatWorkspaceSuffix(name, creditsLeft)}`,
332
+ unpaidPlan: subscription === undefined ? false : isUnpaidPlan(subscription),
333
+ };
334
+ }
335
+ /**
336
+ * Best-effort: true only when we can see an Orb $0 plan. A failed lookup or a
337
+ * signed-out session leaves the pin off rather than guessing.
338
+ */
339
+ async function resolveUnpaidPlan() {
340
+ if (isSignedIn() === false) {
341
+ return false;
342
+ }
343
+ const subscription = await fetchSubscription(getApi());
344
+ if (subscription === undefined) {
345
+ return false;
346
+ }
347
+ return isUnpaidPlan(subscription);
310
348
  }
311
349
  start
312
350
  .then(() => maybeRefreshUpdateCache())
@@ -1,4 +1,4 @@
1
- import type { CodingAgent, PaletteLayout, PinnedRow } from "@cargo-ai/cdk/cli";
1
+ import { type CodingAgent, type PaletteLayout, type PinnedRow } from "@cargo-ai/cdk/cli";
2
2
  export type PaletteLayoutInput = {
3
3
  signedIn: boolean;
4
4
  agents: readonly CodingAgent[];
@@ -20,6 +20,11 @@ export type PaletteLayoutInput = {
20
20
  * on screen or one somewhere above it.
21
21
  */
22
22
  cwd: string;
23
+ /**
24
+ * Pin "Book a demo" when the workspace is unpaid (Orb + $0 plan). Omit or
25
+ * false leaves it in the last section only.
26
+ */
27
+ unpaidPlan?: boolean;
23
28
  };
24
29
  export declare function buildPaletteLayout(input: PaletteLayoutInput): PaletteLayout;
25
30
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"paletteLayout.d.ts","sourceRoot":"","sources":["../src/paletteLayout.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAwE/E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,4EAA4E;IAC5E,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC;;;;;;;;OAQG;IACH,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAM3E;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,kBAAkB,GAAG,SAAS,EAAE,CA4CjE"}
1
+ {"version":3,"file":"paletteLayout.d.ts","sourceRoot":"","sources":["../src/paletteLayout.ts"],"names":[],"mappings":"AAYA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AA8E3B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,4EAA4E;IAC5E,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC;;;;;;;;OAQG;IACH,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAS3E;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,kBAAkB,GAAG,SAAS,EAAE,CA+DjE"}
@@ -8,18 +8,22 @@
8
8
  // down behind `start`. This is the missing opinion, kept in one place and as
9
9
  // data, so it can be read and tested rather than inferred from a menu.
10
10
  import { basename, relative, resolve } from "node:path";
11
+ import { ASK, } from "@cargo-ai/cdk/cli";
11
12
  /** Pinned row values. The leading space keeps them out of the command namespace. */
12
13
  const SIGN_IN = " sign-in";
13
14
  const DEMO = " demo";
14
15
  const CODE = " code";
15
16
  const ADD = " add";
16
17
  const DEPLOY = " deploy";
18
+ const BOOK_DEMO = " book-demo";
17
19
  /**
18
20
  * `start` runs most of these; the pinned row is the shortcut to one of them.
19
21
  * The exceptions are "Add" and "Deploy", which run `cdk add` and `cdk deploy`
20
22
  * directly: neither is a `start` destination, because neither needs the sign-in
21
23
  * step nor a choice of where to carry on — you are already in the project. Bare
22
- * `cdk add` asks connector vs cookbook, then shows that kind's list.
24
+ * `cdk add` asks connector vs cookbook, then shows that kind's list. "Book a
25
+ * demo" is the other exception: it is only pinned on an unpaid plan, and runs
26
+ * `book-demo` itself.
23
27
  */
24
28
  const ENTRANCE = "start";
25
29
  /**
@@ -28,16 +32,19 @@ const ENTRANCE = "start";
28
32
  * opening a menu is looking for.
29
33
  *
30
34
  * `start` is hidden because its destinations are pinned above: a row that
31
- * opens a menu of rows already on screen is a detour. `version` is
32
- * `--version`, and `doctor` reports it anyway.
35
+ * opens a menu of rows already on screen is a detour. `ask` is the same kind
36
+ * of entrance — pinned as "Ask Cargo" — so drawing it again in the tree is a
37
+ * second door to the same room. `version` is `--version`, and `doctor`
38
+ * reports it anyway. `book-demo` is hidden only when it is pinned (see
39
+ * `buildPaletteLayout`); otherwise it stays in the last section.
33
40
  */
34
- const HIDDEN = [ENTRANCE, "version"];
41
+ const HIDDEN = [ENTRANCE, "ask", "version"];
35
42
  /**
36
43
  * The sections, in reading order: everything the workspace is made of, then
37
44
  * the workspace as code on its own, then the machine you are sitting at —
38
- * which ends beside `/exit`, since leaving and checking your setup are the
39
- * same kind of errand. What people reach for most is not here at all; those
40
- * are the pinned rows, above the first section.
45
+ * which ends beside `/exit`, since leaving, checking your setup, and talking
46
+ * to sales are the same kind of errand. What people reach for most is not
47
+ * here at all; those are the pinned rows, above the first section.
41
48
  *
42
49
  * Anything a release adds and nobody lists here still appears, in tree order,
43
50
  * in a final section — a new command is never invisible by omission. So a new
@@ -72,13 +79,15 @@ const SECTIONS = [
72
79
  // The workspace as code sits on its own: it is the same resources again,
73
80
  // declared in a repo rather than run from here.
74
81
  ["cdk"],
75
- ["doctor", "whoami", "login", "logout"],
82
+ ["doctor", "whoami", "login", "logout", "book-demo"],
76
83
  ];
77
84
  export function buildPaletteLayout(input) {
85
+ const pinBookDemo = input.signedIn === true && input.unpaidPlan === true;
78
86
  return {
79
87
  pinned: pinnedRows(input),
80
- hide: HIDDEN,
88
+ hide: pinBookDemo === true ? [...HIDDEN, "book-demo"] : HIDDEN,
81
89
  sections: SECTIONS,
90
+ placeholder: "type to filter, or ask a question",
82
91
  };
83
92
  }
84
93
  /**
@@ -119,7 +128,23 @@ export function pinnedRows(input) {
119
128
  argv: [ENTRANCE, "--continue", "code"],
120
129
  },
121
130
  ];
131
+ const bookDemoRow = input.unpaidPlan === true
132
+ ? [
133
+ {
134
+ value: BOOK_DEMO,
135
+ label: "Book a demo",
136
+ hint: "talk to sales",
137
+ argv: ["book-demo"],
138
+ },
139
+ ]
140
+ : [];
122
141
  return [
142
+ {
143
+ value: ASK,
144
+ label: "Ask Cargo",
145
+ hint: "describe what you want, in plain English",
146
+ argv: ["ask"],
147
+ },
123
148
  ...input.agents.map((agent) => ({
124
149
  value: ` agent:${agent.bin}`,
125
150
  label: `Open ${agent.label}`,
@@ -127,6 +152,7 @@ export function pinnedRows(input) {
127
152
  argv: [ENTRANCE, "--continue", agent.bin],
128
153
  })),
129
154
  ...projectRows,
155
+ ...bookDemoRow,
130
156
  ];
131
157
  }
132
158
  /** The two rows for a palette standing in the CDK project rooted at `root`. */
@@ -5,15 +5,28 @@ export declare function resolveDefaultExport(mod: {
5
5
  * Load a `.ts`/`.js` module through the tsx ESM loader (so `.ts` sources and
6
6
  * their imports of `@cargo-ai/*` / `zod` are transpiled on the fly) and return
7
7
  * its resolved default export. Shared by both `--file` loaders: the workflow
8
- * loader validates the result as a compiled workflow; the agent loader reads the
9
- * agent back out of the CDK registry that loading populated (so it must
10
- * `resetRegistry()` BEFORE calling this). `subject` labels the file in errors
11
- * (e.g. "Workflow", "Agent").
8
+ * loader validates the result as a compiled workflow; the agent loader reads
9
+ * the exported handle to learn which agent the file declares, then loads the
10
+ * whole project for the nodes. `subject` labels the file in errors (e.g.
11
+ * "Workflow", "Agent").
12
12
  */
13
13
  export declare function importModuleDefault(file: string, subject: string): Promise<{
14
14
  absPath: string;
15
15
  defaultExport: unknown;
16
16
  }>;
17
+ /**
18
+ * The CDK project directory a `--file` module belongs to — the directory `cdk
19
+ * plan` and `cdk deploy` run in, which is what a harness agent's inferred
20
+ * `rootDirectory` is measured from. Walk up to the repo, then back down to the
21
+ * project (`infra/` in a scaffolded repo); a file in no recognisable project
22
+ * answers its own directory.
23
+ *
24
+ * Deliberately NOT the nearest cargo.state.json. That file's position is
25
+ * incidental — a repo deployed before `cdk deploy` ran from the project has one
26
+ * at the repo root — so measuring from it would report no `rootDirectory` and
27
+ * clone the repo root, while the deployed agent clones `infra/`.
28
+ */
29
+ export declare function cdkProjectDirFor(file: string): string;
17
30
  /**
18
31
  * Deep-resolve every `@cargo-ai/cdk` handle token in `value` to its real uuid
19
32
  * using the nearest cargo.state.json (searched from `file`'s directory upward,
@@ -1 +1 @@
1
- {"version":3,"file":"cdkState.d.ts","sourceRoot":"","sources":["../../src/utils/cdkState.ts"],"names":[],"mappings":"AAmBA,wBAAgB,oBAAoB,CAAC,GAAG,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CASxE;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAAC,CAyBtD;AAaD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAuCT"}
1
+ {"version":3,"file":"cdkState.d.ts","sourceRoot":"","sources":["../../src/utils/cdkState.ts"],"names":[],"mappings":"AAoBA,wBAAgB,oBAAoB,CAAC,GAAG,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CASxE;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAAC,CAyBtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOrD;AAaD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAuCT"}