@cargo-ai/cli 1.0.120 → 1.0.122

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 (34) hide show
  1. package/README.md +2 -1
  2. package/build/api.d.ts +6 -1
  3. package/build/api.d.ts.map +1 -1
  4. package/build/commands/connection/action.d.ts +1 -1
  5. package/build/commands/connection/action.d.ts.map +1 -1
  6. package/build/commands/connection/action.js +4 -2
  7. package/build/commands/connection/index.d.ts +1 -1
  8. package/build/commands/connection/index.d.ts.map +1 -1
  9. package/build/commands/connection/index.js +4 -4
  10. package/build/commands/connection/integration.d.ts +1 -1
  11. package/build/commands/connection/integration.d.ts.map +1 -1
  12. package/build/commands/connection/integration.js +11 -5
  13. package/build/commands/connection/nativeIntegration.d.ts +1 -1
  14. package/build/commands/connection/nativeIntegration.d.ts.map +1 -1
  15. package/build/commands/connection/nativeIntegration.js +4 -2
  16. package/build/commands/content/file.d.ts.map +1 -1
  17. package/build/commands/content/file.js +163 -2
  18. package/build/commands/orchestration/action.d.ts +1 -1
  19. package/build/commands/orchestration/action.d.ts.map +1 -1
  20. package/build/commands/orchestration/action.js +100 -4
  21. package/build/commands/orchestration/index.d.ts +1 -1
  22. package/build/commands/orchestration/index.d.ts.map +1 -1
  23. package/build/commands/orchestration/index.js +2 -2
  24. package/build/commands/signedOutNotice.d.ts +4 -0
  25. package/build/commands/signedOutNotice.d.ts.map +1 -0
  26. package/build/commands/signedOutNotice.js +11 -0
  27. package/build/index.js +18 -3
  28. package/build/utils/actionDryRun.d.ts +90 -0
  29. package/build/utils/actionDryRun.d.ts.map +1 -0
  30. package/build/utils/actionDryRun.js +145 -0
  31. package/build/utils/sampleFromSchema.d.ts +15 -0
  32. package/build/utils/sampleFromSchema.d.ts.map +1 -0
  33. package/build/utils/sampleFromSchema.js +474 -0
  34. package/package.json +6 -5
@@ -0,0 +1,90 @@
1
+ import { type SampleSubject } from "./sampleFromSchema.js";
2
+ /** A single action runs as one node with this slug (`ACTION_NODE_SLUG`). */
3
+ export declare const DRY_RUN_NODE_SLUG = "action";
4
+ export declare const DRY_RUN_NOTE = "Sample data generated from the output schema. Nothing ran and no credits were used.";
5
+ export type DryRunCreditsCost = {
6
+ type: string;
7
+ cost: number;
8
+ unit?: string;
9
+ unitsCount?: number;
10
+ fixedCost?: number;
11
+ config?: {
12
+ jsonSchema?: unknown;
13
+ };
14
+ };
15
+ /** The fields of an integration or native action this needs. */
16
+ export type DryRunActionDefinition = {
17
+ name?: string;
18
+ config?: {
19
+ schema?: unknown;
20
+ };
21
+ output?: {
22
+ schema?: unknown;
23
+ };
24
+ credits?: {
25
+ costs?: DryRunCreditsCost[];
26
+ };
27
+ };
28
+ export type DataValidation = {
29
+ valid: true;
30
+ } | {
31
+ valid: false;
32
+ errors: string[];
33
+ };
34
+ export type CreditsEstimate = {
35
+ /** What one call costs; for a metered price, one unit or one block of them. */
36
+ credits: number;
37
+ /** How the number was reached, and what it scales with when it does. */
38
+ formula: string;
39
+ };
40
+ export type DryRunResult = {
41
+ run: {
42
+ status: "success";
43
+ executions: {
44
+ nodeSlug: string;
45
+ title: string;
46
+ status: "success";
47
+ creditsUsedCount: number;
48
+ }[];
49
+ };
50
+ runContext: {
51
+ action: unknown;
52
+ };
53
+ runComputedConfigs: {
54
+ action: unknown;
55
+ };
56
+ dryRun: {
57
+ sample: true;
58
+ estimatedCredits: number;
59
+ creditsFormula: string;
60
+ note: string;
61
+ };
62
+ };
63
+ /**
64
+ * Check `--data` against the action's input schema, the way the run would.
65
+ * A missing or empty schema accepts anything: the action takes no declared
66
+ * inputs, or declares them at run time.
67
+ */
68
+ export declare function validateActionData(schema: unknown, data: unknown): DataValidation;
69
+ /**
70
+ * The price of one call, read the way billing reads it: the first cost entry
71
+ * whose `config.jsonSchema` the inputs match (an LLM model, a phone-or-email
72
+ * toggle), then that entry's shape.
73
+ *
74
+ * A metered price depends on what the call returns, so it is shown for one
75
+ * unit (or one block of them) with the formula that scales it.
76
+ */
77
+ export declare function estimateCredits(costs: DryRunCreditsCost[] | undefined, data: unknown): CreditsEstimate;
78
+ /**
79
+ * Whether the action is about a company or a person, read off its slug and
80
+ * name, so a bare `name` in its output samples as the right kind of name.
81
+ */
82
+ export declare function sampleSubjectFor(actionSlug: string, actionName: string | undefined): SampleSubject;
83
+ export declare function buildDryRunResult(input: {
84
+ title: string;
85
+ data: unknown;
86
+ outputSchema: unknown;
87
+ subject: SampleSubject;
88
+ estimate: CreditsEstimate;
89
+ }): DryRunResult;
90
+ //# sourceMappingURL=actionDryRun.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actionDryRun.d.ts","sourceRoot":"","sources":["../../src/utils/actionDryRun.ts"],"names":[],"mappings":"AASA,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE7E,4EAA4E;AAC5E,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAE1C,eAAO,MAAM,YAAY,wFAC8D,CAAC;AAExF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACnC,CAAC;AAEF,gEAAgE;AAChE,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9B,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9B,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAA;KAAE,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,cAAc,GACtB;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEvC,MAAM,MAAM,eAAe,GAAG;IAC5B,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE;QACH,MAAM,EAAE,SAAS,CAAC;QAClB,UAAU,EAAE;YACV,QAAQ,EAAE,MAAM,CAAC;YACjB,KAAK,EAAE,MAAM,CAAC;YACd,MAAM,EAAE,SAAS,CAAC;YAClB,gBAAgB,EAAE,MAAM,CAAC;SAC1B,EAAE,CAAC;KACL,CAAC;IACF,UAAU,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAChC,kBAAkB,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IACxC,MAAM,EAAE;QACN,MAAM,EAAE,IAAI,CAAC;QACb,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,OAAO,GACZ,cAAc,CAYhB;AAkBD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,iBAAiB,EAAE,GAAG,SAAS,EACtC,IAAI,EAAE,OAAO,GACZ,eAAe,CAiDjB;AAWD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,aAAa,CA2Bf;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,eAAe,CAAC;CAC3B,GAAG,YAAY,CAwBf"}
@@ -0,0 +1,145 @@
1
+ // The pure half of `cargo-ai orchestration action execute --dry-run`: check the
2
+ // inputs against the action's own schema, price the call, and dress a sample
3
+ // output in the shape a real waited run returns. The command fetches the
4
+ // action definition and hands it here; nothing in this file touches the
5
+ // network.
6
+ import { validate as jsonSchemaValidate } from "jsonschema";
7
+ import { sampleFromSchema } from "./sampleFromSchema.js";
8
+ /** A single action runs as one node with this slug (`ACTION_NODE_SLUG`). */
9
+ export const DRY_RUN_NODE_SLUG = "action";
10
+ export const DRY_RUN_NOTE = "Sample data generated from the output schema. Nothing ran and no credits were used.";
11
+ /**
12
+ * Check `--data` against the action's input schema, the way the run would.
13
+ * A missing or empty schema accepts anything: the action takes no declared
14
+ * inputs, or declares them at run time.
15
+ */
16
+ export function validateActionData(schema, data) {
17
+ if (isObject(schema) === false || Object.keys(schema).length === 0) {
18
+ return { valid: true };
19
+ }
20
+ const result = jsonSchemaValidate(data, schema);
21
+ if (result.valid === true) {
22
+ return { valid: true };
23
+ }
24
+ return { valid: false, errors: result.errors.map(formatValidationError) };
25
+ }
26
+ function formatValidationError(error) {
27
+ const path = error.property
28
+ .replace(/^instance\.?/, "")
29
+ .replace(/^\[/, "")
30
+ .replace(/\]\[/g, ".")
31
+ .replace(/[[\]]/g, "");
32
+ if (error.name === "required" && typeof error.argument === "string") {
33
+ const field = path === "" ? error.argument : `${path}.${error.argument}`;
34
+ return `Missing required field: ${field}`;
35
+ }
36
+ return `${path === "" ? "data" : path}: ${error.message}`;
37
+ }
38
+ /**
39
+ * The price of one call, read the way billing reads it: the first cost entry
40
+ * whose `config.jsonSchema` the inputs match (an LLM model, a phone-or-email
41
+ * toggle), then that entry's shape.
42
+ *
43
+ * A metered price depends on what the call returns, so it is shown for one
44
+ * unit (or one block of them) with the formula that scales it.
45
+ */
46
+ export function estimateCredits(costs, data) {
47
+ if (costs === undefined || costs.length === 0) {
48
+ return { credits: 0, formula: "This action costs no credits." };
49
+ }
50
+ const cost = costs.find((entry) => {
51
+ if (entry.config === undefined || entry.config.jsonSchema === undefined) {
52
+ return true;
53
+ }
54
+ return (jsonSchemaValidate(data, entry.config.jsonSchema).valid === true);
55
+ });
56
+ if (cost === undefined) {
57
+ return {
58
+ credits: 0,
59
+ formula: "No price matches these inputs, so billing would charge nothing for them.",
60
+ };
61
+ }
62
+ const fixedCost = cost.fixedCost === undefined ? 0 : cost.fixedCost;
63
+ const base = fixedCost === 0 ? "" : `${formatCredits(fixedCost)} + `;
64
+ if (cost.type === "unit") {
65
+ const unit = cost.unit === undefined ? "unit" : cost.unit;
66
+ return {
67
+ credits: roundCredits(fixedCost + cost.cost),
68
+ formula: `${base}${formatCredits(cost.cost)} × <${unit}s returned> credits (shown for 1 ${unit})`,
69
+ };
70
+ }
71
+ if (cost.type === "package") {
72
+ const unit = cost.unit === undefined ? "unit" : cost.unit;
73
+ const unitsCount = cost.unitsCount === undefined ? 1 : cost.unitsCount;
74
+ return {
75
+ credits: roundCredits(fixedCost + cost.cost),
76
+ formula: `${base}${formatCredits(cost.cost)} × ceil(<${unit}s used> / ${String(unitsCount)}) credits (shown for one block of ${String(unitsCount)} ${unit}s)`,
77
+ };
78
+ }
79
+ return {
80
+ credits: roundCredits(cost.cost),
81
+ formula: `${formatCredits(cost.cost)} credits per call`,
82
+ };
83
+ }
84
+ /** Prices from the API (`0.175 + 0.025`) print without their float artifacts. */
85
+ function roundCredits(value) {
86
+ return Math.round(value * 10000) / 10000;
87
+ }
88
+ function formatCredits(value) {
89
+ return String(roundCredits(value));
90
+ }
91
+ /**
92
+ * Whether the action is about a company or a person, read off its slug and
93
+ * name, so a bare `name` in its output samples as the right kind of name.
94
+ */
95
+ export function sampleSubjectFor(actionSlug, actionName) {
96
+ const text = `${actionSlug} ${actionName === undefined ? "" : actionName}`
97
+ .toLowerCase()
98
+ .replace(/[^a-z]/g, "");
99
+ if (text.includes("person") ||
100
+ text.includes("people") ||
101
+ text.includes("contact") ||
102
+ text.includes("email") ||
103
+ text.includes("phone") ||
104
+ text.includes("lead")) {
105
+ return "person";
106
+ }
107
+ if (text.includes("company") ||
108
+ text.includes("companies") ||
109
+ text.includes("organization") ||
110
+ text.includes("account") ||
111
+ text.includes("domain")) {
112
+ return "company";
113
+ }
114
+ return "person";
115
+ }
116
+ export function buildDryRunResult(input) {
117
+ return {
118
+ run: {
119
+ status: "success",
120
+ executions: [
121
+ {
122
+ nodeSlug: DRY_RUN_NODE_SLUG,
123
+ title: input.title,
124
+ status: "success",
125
+ creditsUsedCount: 0,
126
+ },
127
+ ],
128
+ },
129
+ runContext: {
130
+ action: sampleFromSchema(input.outputSchema, { subject: input.subject }),
131
+ },
132
+ runComputedConfigs: { action: input.data },
133
+ dryRun: {
134
+ sample: true,
135
+ estimatedCredits: input.estimate.credits,
136
+ creditsFormula: input.estimate.formula,
137
+ note: DRY_RUN_NOTE,
138
+ },
139
+ };
140
+ }
141
+ function isObject(value) {
142
+ return (typeof value === "object" &&
143
+ value !== null &&
144
+ Array.isArray(value) === false);
145
+ }
@@ -0,0 +1,15 @@
1
+ /** What the whole sample is about, which decides what a bare `name` means. */
2
+ export type SampleSubject = "person" | "company";
3
+ export type SampleOptions = {
4
+ /** Defaults to "person". A company enrichment's `name` is a company name. */
5
+ subject?: SampleSubject;
6
+ };
7
+ export declare function sampleFromSchema(schema: unknown, options?: SampleOptions): unknown;
8
+ /**
9
+ * Whether a schema says enough about an output to sample it. `{}`, a bare
10
+ * `{ type: "object" }` and a free-form record all describe "some object", and
11
+ * a sample of one would be `{}` — which reads as "this action returns nothing"
12
+ * rather than "the shape is decided at run time".
13
+ */
14
+ export declare function describesOutput(schema: unknown): boolean;
15
+ //# sourceMappingURL=sampleFromSchema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sampleFromSchema.d.ts","sourceRoot":"","sources":["../../src/utils/sampleFromSchema.ts"],"names":[],"mappings":"AAcA,8EAA8E;AAC9E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjD,MAAM,MAAM,aAAa,GAAG;IAC1B,6EAA6E;IAC7E,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,CAAC;AAmBF,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,OAAO,EACf,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAST;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAExD"}