@cargo-ai/cdk 1.0.6 → 1.0.7
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.
- package/README.md +4 -1
- package/build/src/cli/commands/from.d.ts +65 -0
- package/build/src/cli/commands/from.d.ts.map +1 -0
- package/build/src/cli/commands/from.js +275 -0
- package/build/src/cli/commands/init.d.ts +1 -1
- package/build/src/cli/commands/init.d.ts.map +1 -1
- package/build/src/cli/commands/init.js +32 -13
- package/build/src/cli/commands/types.d.ts.map +1 -1
- package/build/src/cli/commands/types.js +64 -2
- package/build/src/index.d.ts +4 -4
- package/build/src/index.d.ts.map +1 -1
- package/build/src/index.js +2 -2
- package/build/src/resources/agent.d.ts +23 -0
- package/build/src/resources/agent.d.ts.map +1 -1
- package/build/src/resources/agent.js +17 -0
- package/build/src/resources/capacity.d.ts +11 -0
- package/build/src/resources/capacity.d.ts.map +1 -1
- package/build/src/resources/capacity.js +81 -0
- package/build/src/resources/model.d.ts +11 -3
- package/build/src/resources/model.d.ts.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -51,6 +51,9 @@ no global install:
|
|
|
51
51
|
npx @cargo-ai/cdk init my-workspace --template full # every resource type, wired up
|
|
52
52
|
# or: npx @cargo-ai/cdk init my-workspace # minimal 'blank' template
|
|
53
53
|
# or: npx @cargo-ai/cdk init --list-templates # see all templates
|
|
54
|
+
# or: npx @cargo-ai/cdk init my-tam --from getcargohq/cargo-cookbooks/signal-based-tam
|
|
55
|
+
# scaffold from a GitHub source (owner/repo[/folder][@ref]); a cookbook
|
|
56
|
+
# folder also pulls its required siblings via the repo's cargo.scaffold.json
|
|
54
57
|
cd my-workspace && npm install
|
|
55
58
|
```
|
|
56
59
|
|
|
@@ -221,7 +224,7 @@ npm run deploy # create/update resources, write cargo.state.json
|
|
|
221
224
|
Run any command — including the ones without a script — with `npx @cargo-ai/cdk`:
|
|
222
225
|
|
|
223
226
|
```bash
|
|
224
|
-
npx @cargo-ai/cdk init <directory> # scaffold from a template (--template, --list-templates)
|
|
227
|
+
npx @cargo-ai/cdk init <directory> # scaffold from a template (--template, --list-templates) or GitHub (--from owner/repo[/folder][@ref])
|
|
225
228
|
npx @cargo-ai/cdk deploy --prune # also delete resources removed from code
|
|
226
229
|
npx @cargo-ai/cdk deploy --refresh # re-read live resources, re-apply out-of-band changes
|
|
227
230
|
npx @cargo-ai/cdk refresh # read-only: report resources that drifted from code
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export type FromRef = {
|
|
3
|
+
owner: string;
|
|
4
|
+
repo: string;
|
|
5
|
+
/** Repo-relative folder to scaffold ("" = the whole repo). */
|
|
6
|
+
subPath: string;
|
|
7
|
+
/** Branch or tag ("" = the repo's default branch). */
|
|
8
|
+
gitRef: string;
|
|
9
|
+
};
|
|
10
|
+
/** Reject absolute paths, `..`, `.`, and empty segments in repo-relative paths. */
|
|
11
|
+
export declare function assertSafeRepoRelativePath(repoRelativePath: string, label: string): void;
|
|
12
|
+
/** Join `relativePath` under `baseDir` and ensure the result cannot escape it. */
|
|
13
|
+
export declare function resolveWithin(baseDir: string, relativePath: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Parse a `--from` source. Accepts `owner/repo[/sub/path][@ref]`, the same
|
|
16
|
+
* with a `github.com` / `git@github.com:` prefix, and GitHub tree URLs
|
|
17
|
+
* (`github.com/owner/repo/tree/<ref>/<sub/path>`). Returns `undefined` when
|
|
18
|
+
* the source doesn't name a GitHub repo.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseFromRef(raw: string): FromRef | undefined;
|
|
21
|
+
declare const manifestSchema: z.ZodObject<{
|
|
22
|
+
shared: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
23
|
+
folders: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
24
|
+
requires: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
25
|
+
}, z.core.$strip>>>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
export type ScaffoldManifest = z.infer<typeof manifestSchema>;
|
|
28
|
+
export declare const MANIFEST_FILENAME = "cargo.scaffold.json";
|
|
29
|
+
/** Read and validate `cargo.scaffold.json` at the repo root, if present. */
|
|
30
|
+
export declare function readManifest(repoDir: string): Promise<ScaffoldManifest | undefined>;
|
|
31
|
+
export type CopyPlan = {
|
|
32
|
+
/** Repo-relative folders to copy, keeping their path under the target. */
|
|
33
|
+
folders: string[];
|
|
34
|
+
/** Repo-relative files to copy, keeping their path under the target. */
|
|
35
|
+
files: string[];
|
|
36
|
+
/** When true, the single folder's CONTENTS land at the target root. */
|
|
37
|
+
flatten: boolean;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Decide what to copy. A manifest-declared folder keeps the repo layout and
|
|
41
|
+
* brings its transitive `requires` plus the shared root files; anything else
|
|
42
|
+
* is a flat copy of the requested folder (or the whole repo).
|
|
43
|
+
*/
|
|
44
|
+
export declare function planCopies(manifest: ScaffoldManifest | undefined, subPath: string): CopyPlan;
|
|
45
|
+
/**
|
|
46
|
+
* Shallow-clone the repo into a temp dir. Returns the dir and its cleanup.
|
|
47
|
+
* `remoteUrl` overrides the GitHub URL (tests clone from a local repo).
|
|
48
|
+
*/
|
|
49
|
+
export declare function cloneGitHubRepo(ref: FromRef, remoteUrl?: string): Promise<{
|
|
50
|
+
dir: string;
|
|
51
|
+
cleanup: () => Promise<void>;
|
|
52
|
+
}>;
|
|
53
|
+
/**
|
|
54
|
+
* Fetch the source and copy the planned folders/files into `targetDir`,
|
|
55
|
+
* substituting `__APP_NAME__`. Returns the copied repo-relative paths.
|
|
56
|
+
*/
|
|
57
|
+
export declare function scaffoldFromGitHub(payload: {
|
|
58
|
+
ref: FromRef;
|
|
59
|
+
targetDir: string;
|
|
60
|
+
appName: string;
|
|
61
|
+
/** Test-only override — clone from this URL/path instead of github.com. */
|
|
62
|
+
remoteUrl?: string;
|
|
63
|
+
}): Promise<string[]>;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=from.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"from.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/from.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,MAAM,MAAM,OAAO,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF,mFAAmF;AACnF,wBAAgB,0BAA0B,CACxC,gBAAgB,EAAE,MAAM,EACxB,KAAK,EAAE,MAAM,GACZ,IAAI,CAeN;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAW3E;AA0BD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAqD7D;AAED,QAAA,MAAM,cAAc;;;;;iBAKlB,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE9D,eAAO,MAAM,iBAAiB,wBAAwB,CAAC;AAEvD,4EAA4E;AAC5E,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAoCvC;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,wEAAwE;IACxE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,gBAAgB,GAAG,SAAS,EACtC,OAAO,EAAE,MAAM,GACd,QAAQ,CAkBV;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,OAAO,EACZ,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CA8BxD;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAChD,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAsDpB"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
// `cdk init <dir> --from <source>` — scaffold from a GitHub repo instead of a
|
|
2
|
+
// bundled template. The source names a repo or a folder inside one
|
|
3
|
+
// (`owner/repo`, `owner/repo/folder`, `owner/repo/folder@ref`, or a
|
|
4
|
+
// github.com URL). The repo is fetched with a shallow `git clone`, so private
|
|
5
|
+
// sources work through the user's existing git auth.
|
|
6
|
+
//
|
|
7
|
+
// The manifest is OPTIONAL — any repo/folder scaffolds without it. A repo of
|
|
8
|
+
// composable folders (e.g. cargo-cookbooks) can ship a `cargo.scaffold.json`
|
|
9
|
+
// at its root to declare cross-folder dependencies:
|
|
10
|
+
//
|
|
11
|
+
// {
|
|
12
|
+
// "shared": ["package.json", "tsconfig.json"],
|
|
13
|
+
// "folders": { "signal-based-tam": { "requires": ["base-gtm"] } }
|
|
14
|
+
// }
|
|
15
|
+
//
|
|
16
|
+
// When the requested folder is declared there, the scaffold keeps the repo's
|
|
17
|
+
// folder layout and also copies its `requires` folders (transitively) plus the
|
|
18
|
+
// `shared` root files — so cross-folder imports like
|
|
19
|
+
// `../base-gtm/models/accounts` keep resolving. Any other source copies the
|
|
20
|
+
// folder's contents flat into the target directory.
|
|
21
|
+
import { execFile } from "node:child_process";
|
|
22
|
+
import { promises as fs } from "node:fs";
|
|
23
|
+
import { tmpdir } from "node:os";
|
|
24
|
+
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
25
|
+
import { promisify } from "node:util";
|
|
26
|
+
import { z } from "zod";
|
|
27
|
+
import { copyDirectory } from "./templates.js";
|
|
28
|
+
const execFileAsync = promisify(execFile);
|
|
29
|
+
const SEGMENT_PATTERN = /^[\w][\w.-]*$/;
|
|
30
|
+
/** Reject absolute paths, `..`, `.`, and empty segments in repo-relative paths. */
|
|
31
|
+
export function assertSafeRepoRelativePath(repoRelativePath, label) {
|
|
32
|
+
if (repoRelativePath === "") {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (isAbsolute(repoRelativePath)) {
|
|
36
|
+
throw new Error(`Invalid ${label}: absolute paths are not allowed.`);
|
|
37
|
+
}
|
|
38
|
+
const segments = repoRelativePath.split(/[/\\]/);
|
|
39
|
+
for (const segment of segments) {
|
|
40
|
+
if (segment === "" || segment === "." || segment === "..") {
|
|
41
|
+
throw new Error(`Invalid ${label}: "${repoRelativePath}" contains an unsafe path segment.`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Join `relativePath` under `baseDir` and ensure the result cannot escape it. */
|
|
46
|
+
export function resolveWithin(baseDir, relativePath) {
|
|
47
|
+
const resolvedBase = resolve(baseDir);
|
|
48
|
+
const resolved = resolve(resolvedBase, relativePath);
|
|
49
|
+
const rel = relative(resolvedBase, resolved);
|
|
50
|
+
if (rel === "" || rel === ".") {
|
|
51
|
+
return resolvedBase;
|
|
52
|
+
}
|
|
53
|
+
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
54
|
+
throw new Error(`Path "${relativePath}" escapes "${baseDir}".`);
|
|
55
|
+
}
|
|
56
|
+
return resolved;
|
|
57
|
+
}
|
|
58
|
+
function assertSafeSubPath(subPath) {
|
|
59
|
+
try {
|
|
60
|
+
assertSafeRepoRelativePath(subPath, "source folder");
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function validateManifestPaths(manifest) {
|
|
68
|
+
for (const file of manifest.shared) {
|
|
69
|
+
assertSafeRepoRelativePath(file, `${MANIFEST_FILENAME} shared entry`);
|
|
70
|
+
}
|
|
71
|
+
for (const [folder, entry] of Object.entries(manifest.folders)) {
|
|
72
|
+
assertSafeRepoRelativePath(folder, `${MANIFEST_FILENAME} folder key`);
|
|
73
|
+
for (const required of entry.requires) {
|
|
74
|
+
assertSafeRepoRelativePath(required, `${MANIFEST_FILENAME} requires entry for "${folder}"`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Parse a `--from` source. Accepts `owner/repo[/sub/path][@ref]`, the same
|
|
80
|
+
* with a `github.com` / `git@github.com:` prefix, and GitHub tree URLs
|
|
81
|
+
* (`github.com/owner/repo/tree/<ref>/<sub/path>`). Returns `undefined` when
|
|
82
|
+
* the source doesn't name a GitHub repo.
|
|
83
|
+
*/
|
|
84
|
+
export function parseFromRef(raw) {
|
|
85
|
+
const trimmed = raw.trim();
|
|
86
|
+
const isGitHubUrl = /^https?:\/\/(www\.)?github\.com\//.test(trimmed) ||
|
|
87
|
+
/^git@github\.com:/.test(trimmed);
|
|
88
|
+
const stripped = trimmed
|
|
89
|
+
.replace(/^git@github\.com:/, "")
|
|
90
|
+
.replace(/^https?:\/\/(www\.)?github\.com\//, "")
|
|
91
|
+
.replace(/\/+$/, "");
|
|
92
|
+
if (stripped.includes("://") || stripped.startsWith("git@")) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
const atIndex = stripped.lastIndexOf("@");
|
|
96
|
+
const path = atIndex === -1 ? stripped : stripped.slice(0, atIndex);
|
|
97
|
+
const refSuffix = atIndex === -1 ? "" : stripped.slice(atIndex + 1);
|
|
98
|
+
if (atIndex !== -1 && refSuffix === "")
|
|
99
|
+
return undefined;
|
|
100
|
+
const segments = path.split("/").filter((segment) => segment !== "");
|
|
101
|
+
const [owner, repoRaw] = segments;
|
|
102
|
+
if (owner === undefined || repoRaw === undefined)
|
|
103
|
+
return undefined;
|
|
104
|
+
const repo = repoRaw.replace(/\.git$/, "");
|
|
105
|
+
if (!SEGMENT_PATTERN.test(owner) || !SEGMENT_PATTERN.test(repo)) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
// A tree URL pins its ref in the path: owner/repo/tree/<ref>/<sub/path>.
|
|
109
|
+
// Only apply for full GitHub URLs — otherwise "tree" may be a real folder
|
|
110
|
+
// (e.g. owner/repo/tree/my-feature).
|
|
111
|
+
if (isGitHubUrl && segments[2] === "tree") {
|
|
112
|
+
const treeRef = segments[3];
|
|
113
|
+
if (treeRef === undefined || refSuffix !== "")
|
|
114
|
+
return undefined;
|
|
115
|
+
const subPath = segments.slice(4).join("/");
|
|
116
|
+
if (assertSafeSubPath(subPath) === false)
|
|
117
|
+
return undefined;
|
|
118
|
+
return {
|
|
119
|
+
owner,
|
|
120
|
+
repo,
|
|
121
|
+
subPath,
|
|
122
|
+
gitRef: treeRef,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const subPath = segments.slice(2).join("/");
|
|
126
|
+
if (assertSafeSubPath(subPath) === false)
|
|
127
|
+
return undefined;
|
|
128
|
+
return {
|
|
129
|
+
owner,
|
|
130
|
+
repo,
|
|
131
|
+
subPath,
|
|
132
|
+
gitRef: refSuffix,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const manifestSchema = z.object({
|
|
136
|
+
shared: z.array(z.string()).default([]),
|
|
137
|
+
folders: z
|
|
138
|
+
.record(z.string(), z.object({ requires: z.array(z.string()).default([]) }))
|
|
139
|
+
.default({}),
|
|
140
|
+
});
|
|
141
|
+
export const MANIFEST_FILENAME = "cargo.scaffold.json";
|
|
142
|
+
/** Read and validate `cargo.scaffold.json` at the repo root, if present. */
|
|
143
|
+
export async function readManifest(repoDir) {
|
|
144
|
+
const manifestPath = join(repoDir, MANIFEST_FILENAME);
|
|
145
|
+
let raw;
|
|
146
|
+
try {
|
|
147
|
+
raw = await fs.readFile(manifestPath, "utf-8");
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
if (error !== null &&
|
|
151
|
+
typeof error === "object" &&
|
|
152
|
+
"code" in error &&
|
|
153
|
+
error.code === "ENOENT") {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
157
|
+
throw new Error(`Could not read ${MANIFEST_FILENAME} in the source repo: ${message}`);
|
|
158
|
+
}
|
|
159
|
+
let json;
|
|
160
|
+
try {
|
|
161
|
+
json = JSON.parse(raw);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
165
|
+
throw new Error(`Invalid ${MANIFEST_FILENAME} in the source repo: ${message}`);
|
|
166
|
+
}
|
|
167
|
+
const parsed = manifestSchema.safeParse(json);
|
|
168
|
+
if (parsed.success === false) {
|
|
169
|
+
throw new Error(`Invalid ${MANIFEST_FILENAME} in the source repo: ${z.prettifyError(parsed.error)}`);
|
|
170
|
+
}
|
|
171
|
+
validateManifestPaths(parsed.data);
|
|
172
|
+
return parsed.data;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Decide what to copy. A manifest-declared folder keeps the repo layout and
|
|
176
|
+
* brings its transitive `requires` plus the shared root files; anything else
|
|
177
|
+
* is a flat copy of the requested folder (or the whole repo).
|
|
178
|
+
*/
|
|
179
|
+
export function planCopies(manifest, subPath) {
|
|
180
|
+
const declared = manifest === undefined ? undefined : manifest.folders[subPath];
|
|
181
|
+
if (manifest === undefined || declared === undefined || subPath === "") {
|
|
182
|
+
return { folders: [subPath], files: [], flatten: true };
|
|
183
|
+
}
|
|
184
|
+
const folders = [];
|
|
185
|
+
const queue = [subPath];
|
|
186
|
+
while (queue.length > 0) {
|
|
187
|
+
const current = queue.shift();
|
|
188
|
+
if (current === undefined || folders.includes(current))
|
|
189
|
+
continue;
|
|
190
|
+
folders.push(current);
|
|
191
|
+
const entry = manifest.folders[current];
|
|
192
|
+
if (entry !== undefined)
|
|
193
|
+
queue.push(...entry.requires);
|
|
194
|
+
}
|
|
195
|
+
return { folders, files: manifest.shared, flatten: false };
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Shallow-clone the repo into a temp dir. Returns the dir and its cleanup.
|
|
199
|
+
* `remoteUrl` overrides the GitHub URL (tests clone from a local repo).
|
|
200
|
+
*/
|
|
201
|
+
export async function cloneGitHubRepo(ref, remoteUrl) {
|
|
202
|
+
const dir = await fs.mkdtemp(join(tmpdir(), "cargo-cdk-from-"));
|
|
203
|
+
const url = remoteUrl === undefined
|
|
204
|
+
? `https://github.com/${ref.owner}/${ref.repo}.git`
|
|
205
|
+
: remoteUrl;
|
|
206
|
+
const branchArgs = ref.gitRef === "" ? [] : ["--branch", ref.gitRef];
|
|
207
|
+
try {
|
|
208
|
+
await execFileAsync("git", [
|
|
209
|
+
"clone",
|
|
210
|
+
"--depth",
|
|
211
|
+
"1",
|
|
212
|
+
"--quiet",
|
|
213
|
+
...branchArgs,
|
|
214
|
+
url,
|
|
215
|
+
dir,
|
|
216
|
+
]);
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
220
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
221
|
+
throw new Error(`Could not clone ${url}${ref.gitRef === "" ? "" : ` (ref ${ref.gitRef})`}. Is git installed and the repo accessible?\n${message}`);
|
|
222
|
+
}
|
|
223
|
+
// Drop the git metadata so a whole-repo copy never carries it over.
|
|
224
|
+
await fs.rm(join(dir, ".git"), { recursive: true, force: true });
|
|
225
|
+
return {
|
|
226
|
+
dir,
|
|
227
|
+
cleanup: () => fs.rm(dir, { recursive: true, force: true }),
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Fetch the source and copy the planned folders/files into `targetDir`,
|
|
232
|
+
* substituting `__APP_NAME__`. Returns the copied repo-relative paths.
|
|
233
|
+
*/
|
|
234
|
+
export async function scaffoldFromGitHub(payload) {
|
|
235
|
+
const { ref, targetDir, appName, remoteUrl } = payload;
|
|
236
|
+
const rename = [{ from: "__APP_NAME__", to: appName }];
|
|
237
|
+
const { dir, cleanup } = await cloneGitHubRepo(ref, remoteUrl);
|
|
238
|
+
try {
|
|
239
|
+
if (ref.subPath !== "") {
|
|
240
|
+
assertSafeRepoRelativePath(ref.subPath, "source folder");
|
|
241
|
+
const subPathSrc = resolveWithin(dir, ref.subPath);
|
|
242
|
+
const stat = await fs.stat(subPathSrc).catch(() => undefined);
|
|
243
|
+
if (stat === undefined || stat.isDirectory() === false) {
|
|
244
|
+
throw new Error(`"${ref.subPath}" is not a folder in ${ref.owner}/${ref.repo}.`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
const manifest = await readManifest(dir);
|
|
248
|
+
const plan = planCopies(manifest, ref.subPath);
|
|
249
|
+
for (const folder of plan.folders) {
|
|
250
|
+
const src = resolveWithin(dir, folder);
|
|
251
|
+
const dest = plan.flatten ? targetDir : resolveWithin(targetDir, folder);
|
|
252
|
+
const stat = await fs.stat(src).catch(() => undefined);
|
|
253
|
+
if (stat === undefined || stat.isDirectory() === false) {
|
|
254
|
+
throw new Error(`Manifest folder "${folder}" is missing from ${ref.owner}/${ref.repo}.`);
|
|
255
|
+
}
|
|
256
|
+
await copyDirectory(src, dest, rename);
|
|
257
|
+
}
|
|
258
|
+
for (const file of plan.files) {
|
|
259
|
+
const src = resolveWithin(dir, file);
|
|
260
|
+
const stat = await fs.stat(src).catch(() => undefined);
|
|
261
|
+
if (stat === undefined || stat.isFile() === false) {
|
|
262
|
+
throw new Error(`Manifest shared file "${file}" is missing from ${ref.owner}/${ref.repo}.`);
|
|
263
|
+
}
|
|
264
|
+
const raw = await fs.readFile(src, "utf-8");
|
|
265
|
+
const replaced = rename.reduce((current, { from, to }) => current.split(from).join(to), raw);
|
|
266
|
+
const dest = resolveWithin(targetDir, file);
|
|
267
|
+
await fs.mkdir(dirname(dest), { recursive: true });
|
|
268
|
+
await fs.writeFile(dest, replaced, "utf-8");
|
|
269
|
+
}
|
|
270
|
+
return [...plan.folders, ...plan.files].filter((path) => path !== "");
|
|
271
|
+
}
|
|
272
|
+
finally {
|
|
273
|
+
await cleanup();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,WAAW,CAAC;AAmBjD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAoGzD"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { existsSync, readdirSync } from "node:fs";
|
|
2
2
|
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { Option } from "commander";
|
|
4
5
|
import { ExitCodes, failWith, info, success } from "../io.js";
|
|
6
|
+
import { parseFromRef, scaffoldFromGitHub } from "./from.js";
|
|
5
7
|
import { copyDirectory, listTemplates } from "./templates.js";
|
|
6
|
-
// `cdk init <directory> [--template <slug>]` — scaffold a
|
|
7
|
-
// copying one of `@cargo-ai/cdk`'s bundled templates
|
|
8
|
-
//
|
|
8
|
+
// `cdk init <directory> [--template <slug>] [--from <source>]` — scaffold a
|
|
9
|
+
// starter CDK project by copying one of `@cargo-ai/cdk`'s bundled templates
|
|
10
|
+
// (see `--list-templates`) or fetching a GitHub source — e.g. a cookbook:
|
|
11
|
+
// `cdk init my-tam --from getcargohq/cargo-cookbooks/signal-based-tam` — substituting
|
|
12
|
+
// `__APP_NAME__`. Cookbook sources pull their required sibling folders via the
|
|
13
|
+
// repo's `cargo.scaffold.json` (see `./from.ts`).
|
|
9
14
|
const TEMPLATE_DESCRIPTIONS = {
|
|
10
15
|
blank: "Minimal starter — one connector + model + a workflow-backed tool. Good starting point.",
|
|
11
16
|
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,7 +19,10 @@ export function registerInitCommand(parent) {
|
|
|
14
19
|
parent
|
|
15
20
|
.command("init <directory>")
|
|
16
21
|
.description("Scaffold a starter Cargo CDK project locally from a template (ready to plan/deploy).")
|
|
17
|
-
.
|
|
22
|
+
.addOption(new Option("--template <slug>", "Template slug (default: blank)")
|
|
23
|
+
.default("blank")
|
|
24
|
+
.conflicts("from"))
|
|
25
|
+
.option("--from <source>", "GitHub source to scaffold from instead of a template — owner/repo[/folder][@ref] or a github.com URL. Cookbook folders also pull their required siblings (repo's cargo.scaffold.json).")
|
|
18
26
|
.option("--name <name>", "Project name written into package.json")
|
|
19
27
|
.option("--list-templates", "Print available templates and exit")
|
|
20
28
|
.option("--force", "Write into a non-empty directory")
|
|
@@ -28,11 +36,6 @@ export function registerInitCommand(parent) {
|
|
|
28
36
|
}
|
|
29
37
|
return;
|
|
30
38
|
}
|
|
31
|
-
const templateDir = join(templatesRoot, opts.template);
|
|
32
|
-
if (!existsSync(templateDir)) {
|
|
33
|
-
const slugs = await listTemplates(templatesRoot);
|
|
34
|
-
failWith(`Unknown template "${opts.template}". Available: ${slugs.join(", ")}`, { code: ExitCodes.GenericError });
|
|
35
|
-
}
|
|
36
39
|
const targetDir = resolve(process.cwd(), directory);
|
|
37
40
|
if (existsSync(targetDir) &&
|
|
38
41
|
readdirSync(targetDir).length > 0 &&
|
|
@@ -40,10 +43,26 @@ export function registerInitCommand(parent) {
|
|
|
40
43
|
failWith(`Directory ${directory} is not empty. Pass --force to scaffold into it anyway.`, { code: ExitCodes.GenericError });
|
|
41
44
|
}
|
|
42
45
|
const appName = opts.name !== undefined ? opts.name : basename(targetDir);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
if (opts.from !== undefined) {
|
|
47
|
+
const ref = parseFromRef(opts.from);
|
|
48
|
+
if (ref === undefined) {
|
|
49
|
+
failWith(`Could not parse --from "${opts.from}". Expected owner/repo[/folder][@ref] or a github.com URL.`, { code: ExitCodes.GenericError });
|
|
50
|
+
}
|
|
51
|
+
const copied = await scaffoldFromGitHub({ ref, targetDir, appName });
|
|
52
|
+
const detail = copied.length > 0 ? ` (${copied.join(", ")})` : "";
|
|
53
|
+
success(`Scaffolded ${directory} from ${ref.owner}/${ref.repo}${ref.subPath === "" ? "" : `/${ref.subPath}`}${detail}`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const templateDir = join(templatesRoot, opts.template);
|
|
57
|
+
if (!existsSync(templateDir)) {
|
|
58
|
+
const slugs = await listTemplates(templatesRoot);
|
|
59
|
+
failWith(`Unknown template "${opts.template}". Available: ${slugs.join(", ")}`, { code: ExitCodes.GenericError });
|
|
60
|
+
}
|
|
61
|
+
await copyDirectory(templateDir, targetDir, [
|
|
62
|
+
{ from: "__APP_NAME__", to: appName },
|
|
63
|
+
]);
|
|
64
|
+
success(`Scaffolded ${directory} from the "${opts.template}" template`);
|
|
65
|
+
}
|
|
47
66
|
info(``);
|
|
48
67
|
info([
|
|
49
68
|
`Next steps:`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiHzC,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,IAAI,CAgE7E"}
|
|
@@ -69,7 +69,7 @@ export function registerTypesCommand(parent, getApi) {
|
|
|
69
69
|
].join("\n"));
|
|
70
70
|
info(``);
|
|
71
71
|
const extractorCount = payload.extractorConfigs.reduce((n, e) => n + e.extractors.length, 0);
|
|
72
|
-
info(`Typed ${String(payload.connectorConfigs.length)} connector config(s), ${String(extractorCount)} extractor config(s), ${String(payload.integrations.length)} integration(s), ${String(payload.native.length)} native action(s).`);
|
|
72
|
+
info(`Typed ${String(payload.connectorConfigs.length)} connector config(s), ${String(extractorCount)} extractor config(s), ${String(payload.agentTriggerConfigs.length)} agent trigger config(s), ${String(payload.integrations.length)} integration(s), ${String(payload.native.length)} native action(s).`);
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
75
|
async function fetchWorkspaceSurface(api) {
|
|
@@ -80,7 +80,16 @@ async function fetchWorkspaceSurface(api) {
|
|
|
80
80
|
const native = collectNative(nativeIntegrationResult.nativeIntegration.actions);
|
|
81
81
|
const connectorConfigs = collectConnectorConfigs(rawIntegrations);
|
|
82
82
|
const extractorConfigs = collectExtractorConfigs(rawIntegrations);
|
|
83
|
-
|
|
83
|
+
const extractorSlugs = collectExtractorSlugs(rawIntegrations);
|
|
84
|
+
const agentTriggerConfigs = collectAgentTriggerConfigs(rawIntegrations);
|
|
85
|
+
return {
|
|
86
|
+
integrations,
|
|
87
|
+
native,
|
|
88
|
+
connectorConfigs,
|
|
89
|
+
extractorConfigs,
|
|
90
|
+
extractorSlugs,
|
|
91
|
+
agentTriggerConfigs,
|
|
92
|
+
};
|
|
84
93
|
}
|
|
85
94
|
// integrationSlug → connector config type. Skips integrations whose schema
|
|
86
95
|
// prints as a bare record (no typing gained — the builder already falls back to
|
|
@@ -103,6 +112,27 @@ function collectConnectorConfigs(integrations) {
|
|
|
103
112
|
out.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
104
113
|
return out;
|
|
105
114
|
}
|
|
115
|
+
// integrationSlug → its agent connector-trigger config type. Only a few
|
|
116
|
+
// integrations expose an agent trigger (e.g. slack, http); the rest are skipped,
|
|
117
|
+
// as are those whose schema prints as a bare record.
|
|
118
|
+
function collectAgentTriggerConfigs(integrations) {
|
|
119
|
+
const out = [];
|
|
120
|
+
for (const integration of integrations) {
|
|
121
|
+
const schema = integration.agent?.trigger?.config?.schema;
|
|
122
|
+
if (schema === undefined)
|
|
123
|
+
continue;
|
|
124
|
+
const typeSrc = printJsonSchemaType(schema);
|
|
125
|
+
if (typeSrc === "Record<string, unknown>")
|
|
126
|
+
continue;
|
|
127
|
+
out.push({
|
|
128
|
+
slug: integration.slug,
|
|
129
|
+
name: trimOrUndefined(integration.name),
|
|
130
|
+
typeSrc,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
out.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
134
|
+
return out;
|
|
135
|
+
}
|
|
106
136
|
// integrationSlug → its extractors' config types. Skips extractors whose schema
|
|
107
137
|
// prints as a bare record, and integrations left with none.
|
|
108
138
|
function collectExtractorConfigs(integrations) {
|
|
@@ -125,6 +155,20 @@ function collectExtractorConfigs(integrations) {
|
|
|
125
155
|
out.sort((a, b) => a.integrationSlug.localeCompare(b.integrationSlug));
|
|
126
156
|
return out;
|
|
127
157
|
}
|
|
158
|
+
// integrationSlug → every extractor slug it exposes (the keys of `extractors`),
|
|
159
|
+
// so `defineModel`'s `extractSlug` autocompletes the full set, not just the ones
|
|
160
|
+
// that happen to add a typed config.
|
|
161
|
+
function collectExtractorSlugs(integrations) {
|
|
162
|
+
const out = [];
|
|
163
|
+
for (const integration of integrations) {
|
|
164
|
+
const slugs = Object.keys(integration.extractors ?? {}).sort((a, b) => a.localeCompare(b));
|
|
165
|
+
if (slugs.length === 0)
|
|
166
|
+
continue;
|
|
167
|
+
out.push({ integrationSlug: integration.slug, slugs });
|
|
168
|
+
}
|
|
169
|
+
out.sort((a, b) => a.integrationSlug.localeCompare(b.integrationSlug));
|
|
170
|
+
return out;
|
|
171
|
+
}
|
|
128
172
|
function collectIntegrations(integrations) {
|
|
129
173
|
const out = [];
|
|
130
174
|
for (const integration of integrations) {
|
|
@@ -205,6 +249,24 @@ function renderTypes(payload) {
|
|
|
205
249
|
}
|
|
206
250
|
cdkLines.push(` }`);
|
|
207
251
|
}
|
|
252
|
+
if (payload.extractorSlugs.length > 0) {
|
|
253
|
+
cdkLines.push(` interface ExtractorSlugs {`);
|
|
254
|
+
for (const e of payload.extractorSlugs) {
|
|
255
|
+
const union = e.slugs.map((s) => JSON.stringify(s)).join(" | ");
|
|
256
|
+
cdkLines.push(` ${jsonKey(e.integrationSlug)}: ${union};`);
|
|
257
|
+
}
|
|
258
|
+
cdkLines.push(` }`);
|
|
259
|
+
}
|
|
260
|
+
if (payload.agentTriggerConfigs.length > 0) {
|
|
261
|
+
cdkLines.push(` interface AgentTriggerConfigs {`);
|
|
262
|
+
for (const t of payload.agentTriggerConfigs) {
|
|
263
|
+
const doc = formatJsDoc({ name: t.name ?? t.slug, updatedAt: GENERATED_AT }, " ");
|
|
264
|
+
if (doc !== "")
|
|
265
|
+
cdkLines.push(doc.trimEnd());
|
|
266
|
+
cdkLines.push(` ${jsonKey(t.slug)}: ${t.typeSrc};`);
|
|
267
|
+
}
|
|
268
|
+
cdkLines.push(` }`);
|
|
269
|
+
}
|
|
208
270
|
if (cdkLines.length > 0) {
|
|
209
271
|
blocks.push([`declare module "@cargo-ai/cdk" {`, ...cdkLines, `}`].join("\n"));
|
|
210
272
|
}
|
package/build/src/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export type { ActionOptions, AgentHandle, AgentSpec, AgentUse, ConnectorActionOptions, ModelOptions, } from "./resources/agent.js";
|
|
2
|
-
export { defineAgent } from "./resources/agent.js";
|
|
1
|
+
export type { ActionOptions, AgentHandle, AgentSpec, AgentTriggerConfigs, AgentUse, ConnectorActionOptions, ModelOptions, TriggerSpec, } from "./resources/agent.js";
|
|
2
|
+
export { connectorTrigger, defineAgent } from "./resources/agent.js";
|
|
3
3
|
export type { AppHandle, AppSpec } from "./resources/app.js";
|
|
4
4
|
export { defineApp } from "./resources/app.js";
|
|
5
5
|
export type { AllocationExpirationPolicy, CapacityColor, CapacityHandle, CapacitySpec, } from "./resources/capacity.js";
|
|
6
|
-
export { defineCapacity } from "./resources/capacity.js";
|
|
6
|
+
export { defineCapacity, memberIds } from "./resources/capacity.js";
|
|
7
7
|
export type { ConnectorConfigs, ConnectorHandle, ConnectorSpec, } from "./resources/connector.js";
|
|
8
8
|
export { defineConnector } from "./resources/connector.js";
|
|
9
9
|
export type { ContextHandle, ContextSpec } from "./resources/context.js";
|
|
@@ -16,7 +16,7 @@ export type { FolderHandle, FolderKind, FolderSpec, } from "./resources/folder.j
|
|
|
16
16
|
export { defineFolder } from "./resources/folder.js";
|
|
17
17
|
export type { McpServerHandle, McpServerSpec } from "./resources/mcpServer.js";
|
|
18
18
|
export { defineMcpServer } from "./resources/mcpServer.js";
|
|
19
|
-
export type { ExtractorConfigs, ModelHandle, ModelSpec, UnificationColumnSpec, UnificationParentSpec, UnificationSpec, } from "./resources/model.js";
|
|
19
|
+
export type { ExtractorConfigs, ExtractorSlugs, ModelHandle, ModelSpec, UnificationColumnSpec, UnificationParentSpec, UnificationSpec, } from "./resources/model.js";
|
|
20
20
|
export { defineModel } from "./resources/model.js";
|
|
21
21
|
export type { PlayHandle, PlaySpec } from "./resources/play.js";
|
|
22
22
|
export { definePlay } from "./resources/play.js";
|
package/build/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAUA,YAAY,EACV,aAAa,EACb,WAAW,EACX,SAAS,EACT,QAAQ,EACR,sBAAsB,EACtB,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAUA,YAAY,EACV,aAAa,EACb,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,QAAQ,EACR,sBAAsB,EACtB,YAAY,EACZ,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACrE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,YAAY,EACV,0BAA0B,EAC1B,aAAa,EACb,cAAc,EACd,YAAY,GACb,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpE,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,YAAY,EACV,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EACV,YAAY,EACZ,UAAU,EACV,UAAU,GACX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EACV,wBAAwB,EACxB,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,YAAY,EACV,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,YAAY,EACV,UAAU,EACV,QAAQ,EACR,eAAe,EACf,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAMlE,OAAO,EACL,QAAQ,EACR,cAAc,EACd,uBAAuB,EACvB,OAAO,EACP,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,wBAAwB,CAAC;AAGhC,YAAY,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,KAAK,GACN,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,GAAG,EACH,QAAQ,EACR,OAAO,EACP,cAAc,EACd,MAAM,EACN,KAAK,GACN,MAAM,WAAW,CAAC;AAGnB,YAAY,EACV,QAAQ,EACR,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,SAAS,EACT,SAAS,EACT,QAAQ,EACR,OAAO,EACP,WAAW,EACX,UAAU,EACV,OAAO,GACR,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,SAAS,EACT,SAAS,EACT,QAAQ,EACR,OAAO,EACP,OAAO,EACP,UAAU,GACX,MAAM,WAAW,CAAC;AAGnB,cAAc,mBAAmB,CAAC"}
|
package/build/src/index.js
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
// "c", { datasetUuid: connector.datasetUuid })`). `plan`/`apply`/`deploy`
|
|
7
7
|
// reconcile the graph. The heavier, independently-published workflow + worker
|
|
8
8
|
// SDKs are re-exported so they're reachable from the same import.
|
|
9
|
-
export { defineAgent } from "./resources/agent.js";
|
|
9
|
+
export { connectorTrigger, defineAgent } from "./resources/agent.js";
|
|
10
10
|
export { defineApp } from "./resources/app.js";
|
|
11
|
-
export { defineCapacity } from "./resources/capacity.js";
|
|
11
|
+
export { defineCapacity, memberIds } from "./resources/capacity.js";
|
|
12
12
|
export { defineConnector } from "./resources/connector.js";
|
|
13
13
|
export { defineContext } from "./resources/context.js";
|
|
14
14
|
export { defineCustomIntegration } from "./resources/customIntegration.js";
|
|
@@ -19,6 +19,29 @@ export type TriggerSpec = {
|
|
|
19
19
|
config?: Record<string, unknown>;
|
|
20
20
|
name?: string;
|
|
21
21
|
};
|
|
22
|
+
export interface AgentTriggerConfigs {
|
|
23
|
+
}
|
|
24
|
+
type AgentTriggerConfigFor<S extends string> = S extends keyof AgentTriggerConfigs ? AgentTriggerConfigs[S] : Record<string, unknown>;
|
|
25
|
+
/**
|
|
26
|
+
* Build a connector trigger with per-integration typed `config`. TypeScript
|
|
27
|
+
* can't type a bare trigger object literal inside the `triggers` array — it
|
|
28
|
+
* can't infer each element's `integration` through the array — so this helper
|
|
29
|
+
* narrows `config` to the integration's schema from the single `integration`
|
|
30
|
+
* argument (the same single-object inference `defineConnector` relies on):
|
|
31
|
+
*
|
|
32
|
+
* connectorTrigger({ integration: "slack", connector: slack,
|
|
33
|
+
* config: { channelIds: ["C0XXXX"] } })
|
|
34
|
+
*
|
|
35
|
+
* A bare `{ type: "connector", … }` object still works too, with `config` left
|
|
36
|
+
* as a loose `Record<string, unknown>`. Config schemas are populated by
|
|
37
|
+
* `cargo-ai cdk types`; an unsynced/custom integration keeps the loose record.
|
|
38
|
+
*/
|
|
39
|
+
export declare function connectorTrigger<S extends string>(spec: {
|
|
40
|
+
integration: S;
|
|
41
|
+
connector?: ConnectorHandle | ConnectorRef;
|
|
42
|
+
config?: AgentTriggerConfigFor<S>;
|
|
43
|
+
name?: string;
|
|
44
|
+
}): TriggerSpec;
|
|
22
45
|
export type AgentSpec = {
|
|
23
46
|
name?: string;
|
|
24
47
|
description?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/resources/agent.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAwB,KAAK,KAAK,EAAS,MAAM,YAAY,CAAC;AACrE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAW,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,KAAK,QAAQ,EAAiB,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,YAAY,EACV,aAAa,EACb,QAAQ,EACR,sBAAsB,EACtB,YAAY,GACb,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;AAE7E,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3D;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,SAAS,CAAC,EAAE,eAAe,GAAG,YAAY,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/resources/agent.ts"],"names":[],"mappings":"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"}
|