@cargo-ai/cli 1.0.25 → 1.0.26

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 (30) hide show
  1. package/README.md +17 -17
  2. package/build/commands/cdk/index.d.ts +4 -0
  3. package/build/commands/cdk/index.d.ts.map +1 -0
  4. package/build/commands/cdk/index.js +539 -0
  5. package/build/commands/cdk/init.d.ts +3 -0
  6. package/build/commands/cdk/init.d.ts.map +1 -0
  7. package/build/commands/cdk/init.js +86 -0
  8. package/build/commands/{workflow → cdk}/inputTypes.d.ts +6 -0
  9. package/build/commands/cdk/inputTypes.d.ts.map +1 -0
  10. package/build/commands/{workflow → cdk}/inputTypes.js +115 -17
  11. package/build/commands/cdk/types.d.ts +4 -0
  12. package/build/commands/cdk/types.d.ts.map +1 -0
  13. package/build/commands/{workflow/sync.js → cdk/types.js} +139 -208
  14. package/build/commands/hosting/app.js +1 -1
  15. package/build/commands/hosting/worker.js +1 -1
  16. package/build/commands/runHandler.d.ts +5 -1
  17. package/build/commands/runHandler.d.ts.map +1 -1
  18. package/build/commands/runHandler.js +36 -4
  19. package/build/commands/templateUtils.d.ts.map +1 -0
  20. package/build/index.js +2 -0
  21. package/package.json +4 -3
  22. package/build/commands/hosting/templateUtils.d.ts.map +0 -1
  23. package/build/commands/workflow/index.d.ts +0 -4
  24. package/build/commands/workflow/index.d.ts.map +0 -1
  25. package/build/commands/workflow/index.js +0 -10
  26. package/build/commands/workflow/inputTypes.d.ts.map +0 -1
  27. package/build/commands/workflow/sync.d.ts +0 -4
  28. package/build/commands/workflow/sync.d.ts.map +0 -1
  29. /package/build/commands/{hosting/templateUtils.d.ts → templateUtils.d.ts} +0 -0
  30. /package/build/commands/{hosting/templateUtils.js → templateUtils.js} +0 -0
@@ -0,0 +1,86 @@
1
+ import { existsSync, readdirSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { basename, dirname, join, relative, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { ExitCodes, failWith, info, success } from "../runHandler.js";
6
+ import { copyDirectory, listTemplates } from "../templateUtils.js";
7
+ const require = createRequire(import.meta.url);
8
+ // `cargo-ai cdk init <directory> [--template <slug>]` — scaffold a starter CDK
9
+ // project by copying one of `@cargo-ai/cdk`'s templates (see `--list-templates`),
10
+ // substituting `__APP_NAME__`. Mirrors the hosting app/worker `init` commands.
11
+ const TEMPLATE_DESCRIPTIONS = {
12
+ blank: "Minimal starter — one connector + model + a workflow-backed tool. Good starting point.",
13
+ full: "The full example — every resource type wired into a GTM growth workspace: connectors, models, plays, agents, an MCP server, context, tools, a worker, and a hosted app.",
14
+ };
15
+ export function registerInitCommand(parent) {
16
+ parent
17
+ .command("init <directory>")
18
+ .description("Scaffold a starter Cargo CDK project locally from a template (ready to plan/deploy).")
19
+ .option("--template <slug>", "Template slug (default: blank)", "blank")
20
+ .option("--name <name>", "Project name written into package.json")
21
+ .option("--list-templates", "Print available templates and exit")
22
+ .option("--force", "Write into a non-empty directory")
23
+ .action(async (directory, opts) => {
24
+ const templatesRoot = findTemplatesRoot();
25
+ if (opts.listTemplates === true) {
26
+ const slugs = await listTemplates(templatesRoot);
27
+ for (const slug of slugs) {
28
+ const desc = TEMPLATE_DESCRIPTIONS[slug] ?? "";
29
+ info(`${slug}${desc.length > 0 ? ` — ${desc}` : ""}`);
30
+ }
31
+ return;
32
+ }
33
+ const templateDir = join(templatesRoot, opts.template);
34
+ if (!existsSync(templateDir)) {
35
+ const slugs = await listTemplates(templatesRoot);
36
+ failWith(`Unknown template "${opts.template}". Available: ${slugs.join(", ")}`, { code: ExitCodes.GenericError });
37
+ }
38
+ const targetDir = resolve(process.cwd(), directory);
39
+ if (existsSync(targetDir) &&
40
+ readdirSync(targetDir).length > 0 &&
41
+ opts.force !== true) {
42
+ failWith(`Directory ${directory} is not empty. Pass --force to scaffold into it anyway.`, { code: ExitCodes.GenericError });
43
+ }
44
+ const appName = opts.name !== undefined ? opts.name : basename(targetDir);
45
+ await copyDirectory(templateDir, targetDir, [
46
+ { from: "__APP_NAME__", to: appName },
47
+ ]);
48
+ success(`Scaffolded ${directory} from the "${opts.template}" template`);
49
+ info(``);
50
+ info([
51
+ `Next steps:`,
52
+ ` cd ${relative(process.cwd(), targetDir)}`,
53
+ ` npm install`,
54
+ ` cargo-ai login # authenticate to your workspace`,
55
+ ` cargo-ai cdk types # generate typed connector/model config`,
56
+ ` cargo-ai cdk plan # preview the resource tree`,
57
+ ` cargo-ai cdk deploy # create it in the workspace`,
58
+ ].join("\n"));
59
+ });
60
+ }
61
+ // Templates live in `@cargo-ai/cdk/templates`. Resolve the package entry and walk
62
+ // up to the package root that holds `templates/` — works whether the CDK was
63
+ // installed from npm or came from the monorepo.
64
+ function findTemplatesRoot() {
65
+ try {
66
+ const entry = require.resolve("@cargo-ai/cdk");
67
+ let cursor = dirname(entry);
68
+ for (let i = 0; i < 6; i += 1) {
69
+ const candidate = join(cursor, "templates");
70
+ if (existsSync(candidate))
71
+ return candidate;
72
+ cursor = dirname(cursor);
73
+ }
74
+ }
75
+ catch {
76
+ // Fall through to the monorepo-relative lookup.
77
+ }
78
+ let cursor = dirname(fileURLToPath(import.meta.url));
79
+ for (let i = 0; i < 8; i += 1) {
80
+ const candidate = join(cursor, "packages/cdk/templates");
81
+ if (existsSync(candidate))
82
+ return candidate;
83
+ cursor = dirname(cursor);
84
+ }
85
+ throw new Error("Could not locate @cargo-ai/cdk templates. Make sure @cargo-ai/cdk is installed alongside @cargo-ai/cli.");
86
+ }
@@ -9,6 +9,12 @@ export declare const AGENT_INPUT_TYPE_SRC: string;
9
9
  * object schema we can render.
10
10
  */
11
11
  export declare function printJsonSchemaInput(schema: unknown): string;
12
+ /**
13
+ * Like {@link printJsonSchemaInput} but WITHOUT the top-level `Ref<T> | T`
14
+ * widening — for CDK connector/model config types, which are plain data (no
15
+ * workflow builder Refs). Used by `cargo-ai cdk types`.
16
+ */
17
+ export declare function printJsonSchemaType(schema: unknown): string;
12
18
  /**
13
19
  * Print a tool release's `formFields` as a TS input type. Returns
14
20
  * `undefined` when the fields can't be interpreted (caller falls back to
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputTypes.d.ts","sourceRoot":"","sources":["../../../src/commands/cdk/inputTypes.ts"],"names":[],"mappings":"AAmCA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,QAE+D,CAAC;AAEjG;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAM5D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAQ3D;AAkMD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAU5E"}
@@ -30,12 +30,42 @@ export function printJsonSchemaInput(schema) {
30
30
  if (schema === null || typeof schema !== "object") {
31
31
  return "Record<string, unknown>";
32
32
  }
33
- const printed = printSchema(schema, true);
33
+ const printed = printSchema(schema, true, false);
34
34
  return printed === "unknown" ? "Record<string, unknown>" : printed;
35
35
  }
36
- function printSchema(schema, topLevel) {
36
+ /**
37
+ * Like {@link printJsonSchemaInput} but WITHOUT the top-level `Ref<T> | T`
38
+ * widening — for CDK connector/model config types, which are plain data (no
39
+ * workflow builder Refs). Used by `cargo-ai cdk types`.
40
+ */
41
+ export function printJsonSchemaType(schema) {
42
+ if (schema === null || typeof schema !== "object") {
43
+ return "Record<string, unknown>";
44
+ }
45
+ // encRef=true: print `EncryptionRef` at encryption-typed fields so only those
46
+ // accept a `secret()`.
47
+ const printed = printSchema(schema, false, true);
48
+ return printed === "unknown" ? "Record<string, unknown>" : printed;
49
+ }
50
+ // The platform's shared `encryption` schema definition: an object with a `type`
51
+ // const/enum of "encryption" plus `isEncrypted` and `value`. In CDK config types
52
+ // these positions become `EncryptionRef` (see printObject).
53
+ function isEncryptionSchema(schema) {
54
+ const props = schema.properties;
55
+ if (props === undefined)
56
+ return false;
57
+ const typeProp = props["type"];
58
+ if (typeProp === undefined)
59
+ return false;
60
+ const isEnc = typeProp.const === "encryption" ||
61
+ (Array.isArray(typeProp.enum) &&
62
+ typeProp.enum.length === 1 &&
63
+ typeProp.enum[0] === "encryption");
64
+ return (isEnc && props["isEncrypted"] !== undefined && props["value"] !== undefined);
65
+ }
66
+ function printSchema(schema, topLevel, encRef) {
37
67
  if (Array.isArray(schema.type)) {
38
- return uniqueUnion(schema.type.map((t) => printPrimitive(t, schema, false)));
68
+ return uniqueUnion(schema.type.map((t) => printPrimitive(t, schema, false, encRef)));
39
69
  }
40
70
  if (schema.enum !== undefined && schema.enum.length > 0) {
41
71
  return schema.enum.map((v) => JSON.stringify(v)).join(" | ");
@@ -44,20 +74,26 @@ function printSchema(schema, topLevel) {
44
74
  return JSON.stringify(schema.const);
45
75
  }
46
76
  if (schema.oneOf !== undefined && schema.oneOf.length > 0) {
47
- return uniqueUnion(schema.oneOf.map((s) => printSchema(s, false)));
77
+ return uniqueUnion(schema.oneOf.map((s) => printSchema(s, false, encRef)));
48
78
  }
49
79
  if (schema.anyOf !== undefined && schema.anyOf.length > 0) {
50
- return uniqueUnion(schema.anyOf.map((s) => printSchema(s, false)));
80
+ return uniqueUnion(schema.anyOf.map((s) => printSchema(s, false, encRef)));
51
81
  }
52
82
  if (schema.allOf !== undefined && schema.allOf.length > 0) {
53
- // Conservative: render the head rather than a TS intersection.
54
- return printSchema(schema.allOf[0], topLevel);
83
+ // Connectors model "pick an auth method, then its fields" as an object with
84
+ // a discriminant property plus `allOf: [{ if, then, else }]`. Expand that to
85
+ // a discriminated union (e.g. HubSpot → `{ method: "privateApp"; … } | { …
86
+ // "oauth"; … }`); otherwise fall back to rendering the head.
87
+ const conditional = printConditionalObject(schema, topLevel, encRef);
88
+ if (conditional !== undefined)
89
+ return conditional;
90
+ return printSchema(schema.allOf[0], topLevel, encRef);
55
91
  }
56
92
  if (typeof schema.type !== "string")
57
93
  return "unknown";
58
- return printPrimitive(schema.type, schema, topLevel);
94
+ return printPrimitive(schema.type, schema, topLevel, encRef);
59
95
  }
60
- function printPrimitive(type, schema, topLevel) {
96
+ function printPrimitive(type, schema, topLevel, encRef) {
61
97
  switch (type) {
62
98
  case "string":
63
99
  return "string";
@@ -69,34 +105,96 @@ function printPrimitive(type, schema, topLevel) {
69
105
  case "null":
70
106
  return "null";
71
107
  case "array":
72
- return printArray(schema);
108
+ return printArray(schema, encRef);
73
109
  case "object":
74
- return printObject(schema, topLevel);
110
+ return printObject(schema, topLevel, encRef);
75
111
  default:
76
112
  return "unknown";
77
113
  }
78
114
  }
79
- function printArray(schema) {
115
+ // Expand the connector "discriminant + allOf[{ if, then, else }]" pattern into a
116
+ // discriminated union. Returns undefined when the schema isn't that shape (the
117
+ // caller then falls back to rendering the allOf head).
118
+ function printConditionalObject(schema, topLevel, encRef) {
119
+ const props = schema.properties;
120
+ if (props === undefined || schema.allOf === undefined)
121
+ return undefined;
122
+ const block = schema.allOf.find((a) => a.if !== undefined);
123
+ if (block === undefined || block.if?.properties === undefined)
124
+ return undefined;
125
+ // The discriminant: the single property the `if` tests, and its `const` value.
126
+ const ifEntries = Object.entries(block.if.properties);
127
+ if (ifEntries.length !== 1)
128
+ return undefined;
129
+ const [discKey, discCond] = ifEntries[0];
130
+ const thenValue = discCond.const;
131
+ if (thenValue === undefined)
132
+ return undefined;
133
+ // All the discriminant's allowed values, from its own oneOf/enum consts.
134
+ const discSchema = props[discKey];
135
+ const values = discriminantValues(discSchema);
136
+ if (values.length === 0)
137
+ return undefined;
138
+ const baseRequired = Array.isArray(schema.required) ? schema.required : [];
139
+ const branches = values.map((value) => {
140
+ const isThen = value === thenValue;
141
+ const extra = isThen ? block.then : block.else;
142
+ const branchProps = {
143
+ ...props,
144
+ [discKey]: { const: value },
145
+ };
146
+ if (extra?.properties !== undefined) {
147
+ Object.assign(branchProps, extra.properties);
148
+ }
149
+ const required = new Set(baseRequired);
150
+ if (Array.isArray(extra?.required)) {
151
+ for (const r of extra.required)
152
+ required.add(r);
153
+ }
154
+ return printSchema({ type: "object", properties: branchProps, required: [...required] }, topLevel, encRef);
155
+ });
156
+ return uniqueUnion(branches);
157
+ }
158
+ function discriminantValues(schema) {
159
+ if (schema === undefined)
160
+ return [];
161
+ if (schema.const !== undefined)
162
+ return [schema.const];
163
+ if (Array.isArray(schema.enum))
164
+ return schema.enum;
165
+ const variants = schema.oneOf ?? schema.anyOf;
166
+ if (Array.isArray(variants)) {
167
+ const consts = variants.map((v) => v.const).filter((v) => v !== undefined);
168
+ if (consts.length > 0)
169
+ return consts;
170
+ }
171
+ return [];
172
+ }
173
+ function printArray(schema, encRef) {
80
174
  if (schema.items === undefined)
81
175
  return "unknown[]";
82
176
  if (Array.isArray(schema.items)) {
83
- return `[${schema.items.map((s) => printSchema(s, false)).join(", ")}]`;
177
+ return `[${schema.items.map((s) => printSchema(s, false, encRef)).join(", ")}]`;
84
178
  }
85
- return `Array<${printSchema(schema.items, false)}>`;
179
+ return `Array<${printSchema(schema.items, false, encRef)}>`;
86
180
  }
87
- function printObject(schema, topLevel) {
181
+ function printObject(schema, topLevel, encRef) {
182
+ // An encryption-typed field becomes `EncryptionRef` (which accepts `secret()`)
183
+ // — but only in CDK config mode; workflow input types print it structurally.
184
+ if (encRef && isEncryptionSchema(schema))
185
+ return "EncryptionRef";
88
186
  const props = schema.properties;
89
187
  if (props === undefined) {
90
188
  if (typeof schema.additionalProperties === "object" &&
91
189
  schema.additionalProperties !== null) {
92
- return `Record<string, ${printSchema(schema.additionalProperties, false)}>`;
190
+ return `Record<string, ${printSchema(schema.additionalProperties, false, encRef)}>`;
93
191
  }
94
192
  return "Record<string, unknown>";
95
193
  }
96
194
  const required = new Set(Array.isArray(schema.required) ? schema.required : []);
97
195
  const fields = [];
98
196
  for (const [key, child] of Object.entries(props)) {
99
- const inner = printSchema(child, false);
197
+ const inner = printSchema(child, false, encRef);
100
198
  // Only top-level properties are Ref-widened; nested values are plain.
101
199
  const value = topLevel ? `Ref<${inner}> | ${inner}` : inner;
102
200
  const opt = required.has(key) ? "" : "?";
@@ -0,0 +1,4 @@
1
+ import type { Command } from "commander";
2
+ import type { Api } from "../../api.js";
3
+ export declare function registerTypesCommand(parent: Command, getApi: () => Api): void;
4
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/cdk/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AA0FxC,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI,CA8D7E"}