@usenaive-sdk/cli 0.4.0 → 0.4.1
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/dist/commands/billing-client.d.ts +2 -0
- package/dist/commands/billing-client.js +271 -0
- package/dist/commands/billing-client.js.map +1 -0
- package/dist/commands/crm-app.d.ts +2 -0
- package/dist/commands/crm-app.js +306 -0
- package/dist/commands/crm-app.js.map +1 -0
- package/dist/commands/crm.d.ts +2 -0
- package/dist/commands/crm.js +319 -0
- package/dist/commands/crm.js.map +1 -0
- package/dist/commands/integrations.d.ts +2 -0
- package/dist/commands/integrations.js +199 -0
- package/dist/commands/integrations.js.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { apiRequest, handleApiError } from "../client.js";
|
|
3
|
+
import { agentOutput } from "../output.js";
|
|
4
|
+
export const billingClientCmd = new Command("billing-client")
|
|
5
|
+
.description("naive/billing-client — Stripe-via-Composio: invoice + bill your clients. Distinct from 'naive billing' (Naive platform plan).")
|
|
6
|
+
.addHelpText("after", `
|
|
7
|
+
Subcommands:
|
|
8
|
+
naive billing-client connection Check whether Stripe is connected via Composio
|
|
9
|
+
naive billing-client sync Manually pull latest invoices/subscriptions/customers from Stripe
|
|
10
|
+
naive billing-client invoices ... Manage Stripe invoices for your clients
|
|
11
|
+
naive billing-client subscriptions ... Manage Stripe subscriptions for retainers
|
|
12
|
+
naive billing-client profile <contact-id> Look up a billing profile for a CRM contact
|
|
13
|
+
naive billing-client overdue List overdue invoices (for dunning workflows)
|
|
14
|
+
naive billing-client mrr Net MRR change over a date range
|
|
15
|
+
|
|
16
|
+
Stripe must be connected via Composio first:
|
|
17
|
+
$ naive integrations connect stripe
|
|
18
|
+
|
|
19
|
+
If it isn't connected, every billing-client command returns:
|
|
20
|
+
{ error_code: "stripe_not_connected", connect_url: "..." }
|
|
21
|
+
`);
|
|
22
|
+
billingClientCmd
|
|
23
|
+
.command("connection")
|
|
24
|
+
.description("Check Stripe (Composio) connection status")
|
|
25
|
+
.action(async () => {
|
|
26
|
+
const resp = await apiRequest("GET", "/v1/billing-client/connection");
|
|
27
|
+
handleApiError("billing-client.connection", resp);
|
|
28
|
+
const data = resp.data;
|
|
29
|
+
agentOutput({
|
|
30
|
+
action: "billing-client.connection",
|
|
31
|
+
result: resp.data,
|
|
32
|
+
next_steps: data.connected
|
|
33
|
+
? [{ command: "naive billing-client invoices list", description: "List existing invoices" }]
|
|
34
|
+
: [{ command: "naive integrations connect stripe", description: "Connect Stripe via Composio" }],
|
|
35
|
+
hints: data.connected
|
|
36
|
+
? ["Stripe is connected — billing-client commands will work"]
|
|
37
|
+
: ["Stripe is not connected — connect via Composio before invoicing clients"],
|
|
38
|
+
related_commands: ["naive integrations connect", "naive billing-client invoices list"],
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
billingClientCmd
|
|
42
|
+
.command("sync")
|
|
43
|
+
.description("Manually pull latest invoices/subscriptions/customers from Stripe (usually runs hourly)")
|
|
44
|
+
.action(async () => {
|
|
45
|
+
const resp = await apiRequest("POST", "/v1/billing-client/sync");
|
|
46
|
+
handleApiError("billing-client.sync", resp);
|
|
47
|
+
agentOutput({
|
|
48
|
+
action: "billing-client.sync",
|
|
49
|
+
result: resp.data,
|
|
50
|
+
related_commands: ["naive billing-client invoices list", "naive billing-client subscriptions list"],
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
// ── Invoices ──────────────────────────────────────────────────────────────
|
|
54
|
+
const invoicesCmd = billingClientCmd.command("invoices").description("Stripe invoice management");
|
|
55
|
+
invoicesCmd
|
|
56
|
+
.command("list")
|
|
57
|
+
.description("List invoices (denormalized read model)")
|
|
58
|
+
.option("--crm-contact <id>", "Filter to a CRM contact")
|
|
59
|
+
.option("--crm-company <id>", "Filter to a CRM company")
|
|
60
|
+
.option("--status <status>", "Stripe status (draft|open|paid|void|uncollectible)")
|
|
61
|
+
.option("--limit <n>", "Max results (default 50)", "50")
|
|
62
|
+
.option("--offset <n>", "Pagination offset", "0")
|
|
63
|
+
.action(async (opts) => {
|
|
64
|
+
const params = new URLSearchParams({ limit: opts.limit, offset: opts.offset });
|
|
65
|
+
if (opts.crmContact)
|
|
66
|
+
params.set("crm_contact_id", opts.crmContact);
|
|
67
|
+
if (opts.crmCompany)
|
|
68
|
+
params.set("crm_company_id", opts.crmCompany);
|
|
69
|
+
if (opts.status)
|
|
70
|
+
params.set("status", opts.status);
|
|
71
|
+
const resp = await apiRequest("GET", `/v1/billing-client/invoices?${params}`);
|
|
72
|
+
handleApiError("billing-client.invoices.list", resp);
|
|
73
|
+
const data = resp.data;
|
|
74
|
+
agentOutput({
|
|
75
|
+
action: "billing-client.invoices.list",
|
|
76
|
+
result: resp.data,
|
|
77
|
+
next_steps: data.invoices.length > 0
|
|
78
|
+
? [{ command: `naive billing-client invoices get ${data.invoices[0].id}`, description: "View the most recent invoice" }]
|
|
79
|
+
: [{ command: "naive billing-client invoices create --crm-contact <id> --line-items <json>", description: "Create your first invoice" }],
|
|
80
|
+
hints: [`${data.count} invoice${data.count === 1 ? "" : "s"} returned`],
|
|
81
|
+
related_commands: ["naive billing-client invoices create", "naive billing-client invoices send"],
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
invoicesCmd
|
|
85
|
+
.command("create")
|
|
86
|
+
.description("Create a Stripe invoice for a CRM contact")
|
|
87
|
+
.requiredOption("--crm-contact <id>", "CRM contact UUID")
|
|
88
|
+
.requiredOption("--line-items <json>", "JSON array: [{description, amount_cents, quantity?, currency?}]")
|
|
89
|
+
.option("--memo <text>", "Memo text on the invoice")
|
|
90
|
+
.option("--due-date <iso>", "ISO date string")
|
|
91
|
+
.option("--currency <iso>", "Default currency (usd)")
|
|
92
|
+
.option("--auto-send", "Finalize and send immediately after creation")
|
|
93
|
+
.action(async (opts) => {
|
|
94
|
+
let lineItems;
|
|
95
|
+
try {
|
|
96
|
+
lineItems = JSON.parse(opts.lineItems);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
agentOutput({
|
|
100
|
+
action: "billing-client.invoices.create",
|
|
101
|
+
result: { error: "invalid_input", message: "--line-items must be valid JSON" },
|
|
102
|
+
hints: ["Example: '[{\"description\":\"Audit\",\"amount_cents\":150000}]'"],
|
|
103
|
+
related_commands: ["naive billing-client invoices create"],
|
|
104
|
+
});
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
const resp = await apiRequest("POST", "/v1/billing-client/invoices", {
|
|
108
|
+
crm_contact_id: opts.crmContact,
|
|
109
|
+
line_items: lineItems,
|
|
110
|
+
memo: opts.memo,
|
|
111
|
+
due_date: opts.dueDate,
|
|
112
|
+
currency: opts.currency,
|
|
113
|
+
auto_send: opts.autoSend === true,
|
|
114
|
+
});
|
|
115
|
+
handleApiError("billing-client.invoices.create", resp);
|
|
116
|
+
const data = resp.data;
|
|
117
|
+
agentOutput({
|
|
118
|
+
action: "billing-client.invoices.create",
|
|
119
|
+
result: resp.data,
|
|
120
|
+
next_steps: [
|
|
121
|
+
...(opts.autoSend
|
|
122
|
+
? [{ command: `naive billing-client invoices get ${data.invoice.id}`, description: "Verify invoice was sent" }]
|
|
123
|
+
: [{ command: `naive billing-client invoices send ${data.invoice.id}`, description: "Finalize and send this draft invoice" }]),
|
|
124
|
+
],
|
|
125
|
+
hints: data.invoice.hosted_invoice_url ? [`Hosted: ${data.invoice.hosted_invoice_url}`] : [],
|
|
126
|
+
related_commands: ["naive billing-client invoices send", "naive billing-client invoices void"],
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
invoicesCmd
|
|
130
|
+
.command("get <invoice_id>")
|
|
131
|
+
.description("Get a single invoice")
|
|
132
|
+
.action(async (invoiceId) => {
|
|
133
|
+
const resp = await apiRequest("GET", `/v1/billing-client/invoices/${invoiceId}`);
|
|
134
|
+
handleApiError("billing-client.invoices.get", resp);
|
|
135
|
+
agentOutput({
|
|
136
|
+
action: "billing-client.invoices.get",
|
|
137
|
+
result: resp.data,
|
|
138
|
+
related_commands: ["naive billing-client invoices send", "naive billing-client invoices void"],
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
invoicesCmd
|
|
142
|
+
.command("send <invoice_id>")
|
|
143
|
+
.description("Finalize (if draft) and send a Stripe invoice")
|
|
144
|
+
.action(async (invoiceId) => {
|
|
145
|
+
const resp = await apiRequest("POST", `/v1/billing-client/invoices/${invoiceId}/send`);
|
|
146
|
+
handleApiError("billing-client.invoices.send", resp);
|
|
147
|
+
agentOutput({
|
|
148
|
+
action: "billing-client.invoices.send",
|
|
149
|
+
result: resp.data,
|
|
150
|
+
related_commands: ["naive billing-client invoices get", "naive billing-client invoices list"],
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
invoicesCmd
|
|
154
|
+
.command("void <invoice_id>")
|
|
155
|
+
.description("Void a Stripe invoice")
|
|
156
|
+
.option("--reason <text>", "Why the invoice is being voided")
|
|
157
|
+
.action(async (invoiceId, opts) => {
|
|
158
|
+
const resp = await apiRequest("POST", `/v1/billing-client/invoices/${invoiceId}/void`, {
|
|
159
|
+
reason: opts.reason,
|
|
160
|
+
});
|
|
161
|
+
handleApiError("billing-client.invoices.void", resp);
|
|
162
|
+
agentOutput({
|
|
163
|
+
action: "billing-client.invoices.void",
|
|
164
|
+
result: resp.data,
|
|
165
|
+
related_commands: ["naive billing-client invoices list", "naive billing-client invoices create"],
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
// ── Subscriptions ────────────────────────────────────────────────────────
|
|
169
|
+
const subsCmd = billingClientCmd.command("subscriptions").description("Stripe subscription management (retainers)");
|
|
170
|
+
subsCmd
|
|
171
|
+
.command("list")
|
|
172
|
+
.description("List subscriptions")
|
|
173
|
+
.option("--crm-contact <id>", "Filter to a CRM contact")
|
|
174
|
+
.option("--status <status>", "Stripe status filter")
|
|
175
|
+
.option("--limit <n>", "Max results (default 50)", "50")
|
|
176
|
+
.option("--offset <n>", "Pagination offset", "0")
|
|
177
|
+
.action(async (opts) => {
|
|
178
|
+
const params = new URLSearchParams({ limit: opts.limit, offset: opts.offset });
|
|
179
|
+
if (opts.crmContact)
|
|
180
|
+
params.set("crm_contact_id", opts.crmContact);
|
|
181
|
+
if (opts.status)
|
|
182
|
+
params.set("status", opts.status);
|
|
183
|
+
const resp = await apiRequest("GET", `/v1/billing-client/subscriptions?${params}`);
|
|
184
|
+
handleApiError("billing-client.subscriptions.list", resp);
|
|
185
|
+
agentOutput({
|
|
186
|
+
action: "billing-client.subscriptions.list",
|
|
187
|
+
result: resp.data,
|
|
188
|
+
related_commands: ["naive billing-client subscriptions create", "naive billing-client subscriptions cancel"],
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
subsCmd
|
|
192
|
+
.command("create")
|
|
193
|
+
.description("Create a subscription for a CRM contact")
|
|
194
|
+
.requiredOption("--crm-contact <id>", "CRM contact UUID")
|
|
195
|
+
.requiredOption("--price-id <id>", "Stripe price ID (price_...)")
|
|
196
|
+
.option("--trial-days <n>", "Trial period in days")
|
|
197
|
+
.action(async (opts) => {
|
|
198
|
+
const resp = await apiRequest("POST", "/v1/billing-client/subscriptions", {
|
|
199
|
+
crm_contact_id: opts.crmContact,
|
|
200
|
+
price_id: opts.priceId,
|
|
201
|
+
...(opts.trialDays && { trial_days: parseInt(opts.trialDays, 10) }),
|
|
202
|
+
});
|
|
203
|
+
handleApiError("billing-client.subscriptions.create", resp);
|
|
204
|
+
agentOutput({
|
|
205
|
+
action: "billing-client.subscriptions.create",
|
|
206
|
+
result: resp.data,
|
|
207
|
+
related_commands: ["naive billing-client subscriptions list", "naive billing-client mrr"],
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
subsCmd
|
|
211
|
+
.command("cancel <subscription_id>")
|
|
212
|
+
.description("Cancel a subscription (default: at period end)")
|
|
213
|
+
.option("--immediate", "Cancel immediately rather than at period end")
|
|
214
|
+
.action(async (subscriptionId, opts) => {
|
|
215
|
+
const resp = await apiRequest("POST", `/v1/billing-client/subscriptions/${subscriptionId}/cancel`, {
|
|
216
|
+
at_period_end: !opts.immediate,
|
|
217
|
+
});
|
|
218
|
+
handleApiError("billing-client.subscriptions.cancel", resp);
|
|
219
|
+
agentOutput({
|
|
220
|
+
action: "billing-client.subscriptions.cancel",
|
|
221
|
+
result: resp.data,
|
|
222
|
+
related_commands: ["naive billing-client subscriptions list"],
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
// ── Profiles + aggregates ─────────────────────────────────────────────────
|
|
226
|
+
billingClientCmd
|
|
227
|
+
.command("profile <contact_id>")
|
|
228
|
+
.description("Get the billing profile for a CRM contact (denormalized status, MRR, LTV)")
|
|
229
|
+
.action(async (contactId) => {
|
|
230
|
+
const resp = await apiRequest("GET", `/v1/billing-client/profiles/by-contact/${contactId}`);
|
|
231
|
+
handleApiError("billing-client.profile", resp);
|
|
232
|
+
agentOutput({
|
|
233
|
+
action: "billing-client.profile",
|
|
234
|
+
result: resp.data,
|
|
235
|
+
related_commands: ["naive billing-client invoices list", "naive billing-client subscriptions list"],
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
billingClientCmd
|
|
239
|
+
.command("overdue")
|
|
240
|
+
.description("List overdue invoices (for dunning)")
|
|
241
|
+
.option("--threshold-days <n>", "Only invoices overdue by at least N days", "0")
|
|
242
|
+
.action(async (opts) => {
|
|
243
|
+
const params = new URLSearchParams({ threshold_days: opts.thresholdDays });
|
|
244
|
+
const resp = await apiRequest("GET", `/v1/billing-client/invoices/overdue?${params}`);
|
|
245
|
+
handleApiError("billing-client.overdue", resp);
|
|
246
|
+
agentOutput({
|
|
247
|
+
action: "billing-client.overdue",
|
|
248
|
+
result: resp.data,
|
|
249
|
+
related_commands: ["naive billing-client invoices list", "naive billing-client invoices send"],
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
billingClientCmd
|
|
253
|
+
.command("mrr")
|
|
254
|
+
.description("Compute MRR change over a date range")
|
|
255
|
+
.option("--from <iso>", "Start date (default 30 days ago)")
|
|
256
|
+
.option("--to <iso>", "End date (default now)")
|
|
257
|
+
.action(async (opts) => {
|
|
258
|
+
const params = new URLSearchParams();
|
|
259
|
+
if (opts.from)
|
|
260
|
+
params.set("from", opts.from);
|
|
261
|
+
if (opts.to)
|
|
262
|
+
params.set("to", opts.to);
|
|
263
|
+
const resp = await apiRequest("GET", `/v1/billing-client/mrr?${params}`);
|
|
264
|
+
handleApiError("billing-client.mrr", resp);
|
|
265
|
+
agentOutput({
|
|
266
|
+
action: "billing-client.mrr",
|
|
267
|
+
result: resp.data,
|
|
268
|
+
related_commands: ["naive billing-client subscriptions list"],
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
//# sourceMappingURL=billing-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billing-client.js","sourceRoot":"","sources":["../../src/commands/billing-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,OAAO,CAAC,gBAAgB,CAAC;KAC1D,WAAW,CAAC,+HAA+H,CAAC;KAC5I,WAAW,CAAC,OAAO,EAAE;;;;;;;;;;;;;;;CAevB,CAAC,CAAC;AAEH,gBAAgB;KACb,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,2CAA2C,CAAC;KACxD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,+BAA+B,CAAC,CAAC;IACtE,cAAc,CAAC,2BAA2B,EAAE,IAAI,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAoD,CAAC;IACvE,WAAW,CAAC;QACV,MAAM,EAAE,2BAA2B;QACnC,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,UAAU,EAAE,IAAI,CAAC,SAAS;YACxB,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,oCAAoC,EAAE,WAAW,EAAE,wBAAwB,EAAE,CAAC;YAC5F,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,mCAAmC,EAAE,WAAW,EAAE,6BAA6B,EAAE,CAAC;QAClG,KAAK,EAAE,IAAI,CAAC,SAAS;YACnB,CAAC,CAAC,CAAC,yDAAyD,CAAC;YAC7D,CAAC,CAAC,CAAC,yEAAyE,CAAC;QAC/E,gBAAgB,EAAE,CAAC,4BAA4B,EAAE,oCAAoC,CAAC;KACvF,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,gBAAgB;KACb,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,yFAAyF,CAAC;KACtG,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IACjE,cAAc,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;IAC5C,WAAW,CAAC;QACV,MAAM,EAAE,qBAAqB;QAC7B,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,gBAAgB,EAAE,CAAC,oCAAoC,EAAE,yCAAyC,CAAC;KACpG,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,6EAA6E;AAE7E,MAAM,WAAW,GAAG,gBAAgB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;AAElG,WAAW;KACR,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,oBAAoB,EAAE,yBAAyB,CAAC;KACvD,MAAM,CAAC,oBAAoB,EAAE,yBAAyB,CAAC;KACvD,MAAM,CAAC,mBAAmB,EAAE,oDAAoD,CAAC;KACjF,MAAM,CAAC,aAAa,EAAE,0BAA0B,EAAE,IAAI,CAAC;KACvD,MAAM,CAAC,cAAc,EAAE,mBAAmB,EAAE,GAAG,CAAC;KAChD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/E,IAAI,IAAI,CAAC,UAAU;QAAE,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACnE,IAAI,IAAI,CAAC,UAAU;QAAE,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACnE,IAAI,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAEnD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,+BAA+B,MAAM,EAAE,CAAC,CAAC;IAC9E,cAAc,CAAC,8BAA8B,EAAE,IAAI,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,IAA0D,CAAC;IAC7E,WAAW,CAAC;QACV,MAAM,EAAE,8BAA8B;QACtC,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,UAAU,EACR,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YACtB,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,qCAAqC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;YACzH,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,6EAA6E,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;QAC5I,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC;QACvE,gBAAgB,EAAE,CAAC,sCAAsC,EAAE,oCAAoC,CAAC;KACjG,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,WAAW;KACR,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,2CAA2C,CAAC;KACxD,cAAc,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;KACxD,cAAc,CAAC,qBAAqB,EAAE,iEAAiE,CAAC;KACxG,MAAM,CAAC,eAAe,EAAE,0BAA0B,CAAC;KACnD,MAAM,CAAC,kBAAkB,EAAE,iBAAiB,CAAC;KAC7C,MAAM,CAAC,kBAAkB,EAAE,wBAAwB,CAAC;KACpD,MAAM,CAAC,aAAa,EAAE,8CAA8C,CAAC;KACrE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,SAAkB,CAAC;IACvB,IAAI,CAAC;QACH,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,WAAW,CAAC;YACV,MAAM,EAAE,gCAAgC;YACxC,MAAM,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,iCAAiC,EAAE;YAC9E,KAAK,EAAE,CAAC,kEAAkE,CAAC;YAC3E,gBAAgB,EAAE,CAAC,sCAAsC,CAAC;SAC3D,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,6BAA6B,EAAE;QACnE,cAAc,EAAE,IAAI,CAAC,UAAU;QAC/B,UAAU,EAAE,SAAS;QACrB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,OAAO;QACtB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,SAAS,EAAE,IAAI,CAAC,QAAQ,KAAK,IAAI;KAClC,CAAC,CAAC;IACH,cAAc,CAAC,gCAAgC,EAAE,IAAI,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAsE,CAAC;IACzF,WAAW,CAAC;QACV,MAAM,EAAE,gCAAgC;QACxC,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,UAAU,EAAE;YACV,GAAG,CAAC,IAAI,CAAC,QAAQ;gBACf,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,qCAAqC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,yBAAyB,EAAE,CAAC;gBAC/G,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,sCAAsC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,sCAAsC,EAAE,CAAC,CAAC;SACjI;QACD,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;QAC5F,gBAAgB,EAAE,CAAC,oCAAoC,EAAE,oCAAoC,CAAC;KAC/F,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,WAAW;KACR,OAAO,CAAC,kBAAkB,CAAC;KAC3B,WAAW,CAAC,sBAAsB,CAAC;KACnC,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,EAAE;IAClC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,+BAA+B,SAAS,EAAE,CAAC,CAAC;IACjF,cAAc,CAAC,6BAA6B,EAAE,IAAI,CAAC,CAAC;IACpD,WAAW,CAAC;QACV,MAAM,EAAE,6BAA6B;QACrC,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,gBAAgB,EAAE,CAAC,oCAAoC,EAAE,oCAAoC,CAAC;KAC/F,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,WAAW;KACR,OAAO,CAAC,mBAAmB,CAAC;KAC5B,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,EAAE;IAClC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,+BAA+B,SAAS,OAAO,CAAC,CAAC;IACvF,cAAc,CAAC,8BAA8B,EAAE,IAAI,CAAC,CAAC;IACrD,WAAW,CAAC;QACV,MAAM,EAAE,8BAA8B;QACtC,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,gBAAgB,EAAE,CAAC,mCAAmC,EAAE,oCAAoC,CAAC;KAC9F,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,WAAW;KACR,OAAO,CAAC,mBAAmB,CAAC;KAC5B,WAAW,CAAC,uBAAuB,CAAC;KACpC,MAAM,CAAC,iBAAiB,EAAE,iCAAiC,CAAC;KAC5D,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,IAAI,EAAE,EAAE;IACxC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,+BAA+B,SAAS,OAAO,EAAE;QACrF,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;IACH,cAAc,CAAC,8BAA8B,EAAE,IAAI,CAAC,CAAC;IACrD,WAAW,CAAC;QACV,MAAM,EAAE,8BAA8B;QACtC,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,gBAAgB,EAAE,CAAC,oCAAoC,EAAE,sCAAsC,CAAC;KACjG,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,4EAA4E;AAE5E,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,WAAW,CAAC,4CAA4C,CAAC,CAAC;AAEpH,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,oBAAoB,CAAC;KACjC,MAAM,CAAC,oBAAoB,EAAE,yBAAyB,CAAC;KACvD,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC;KACnD,MAAM,CAAC,aAAa,EAAE,0BAA0B,EAAE,IAAI,CAAC;KACvD,MAAM,CAAC,cAAc,EAAE,mBAAmB,EAAE,GAAG,CAAC;KAChD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/E,IAAI,IAAI,CAAC,UAAU;QAAE,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACnE,IAAI,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAEnD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,oCAAoC,MAAM,EAAE,CAAC,CAAC;IACnF,cAAc,CAAC,mCAAmC,EAAE,IAAI,CAAC,CAAC;IAC1D,WAAW,CAAC;QACV,MAAM,EAAE,mCAAmC;QAC3C,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,gBAAgB,EAAE,CAAC,2CAA2C,EAAE,2CAA2C,CAAC;KAC7G,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,yCAAyC,CAAC;KACtD,cAAc,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;KACxD,cAAc,CAAC,iBAAiB,EAAE,6BAA6B,CAAC;KAChE,MAAM,CAAC,kBAAkB,EAAE,sBAAsB,CAAC;KAClD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,kCAAkC,EAAE;QACxE,cAAc,EAAE,IAAI,CAAC,UAAU;QAC/B,QAAQ,EAAE,IAAI,CAAC,OAAO;QACtB,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC;KACpE,CAAC,CAAC;IACH,cAAc,CAAC,qCAAqC,EAAE,IAAI,CAAC,CAAC;IAC5D,WAAW,CAAC;QACV,MAAM,EAAE,qCAAqC;QAC7C,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,gBAAgB,EAAE,CAAC,yCAAyC,EAAE,0BAA0B,CAAC;KAC1F,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,0BAA0B,CAAC;KACnC,WAAW,CAAC,gDAAgD,CAAC;KAC7D,MAAM,CAAC,aAAa,EAAE,8CAA8C,CAAC;KACrE,MAAM,CAAC,KAAK,EAAE,cAAsB,EAAE,IAAI,EAAE,EAAE;IAC7C,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,oCAAoC,cAAc,SAAS,EAAE;QACjG,aAAa,EAAE,CAAC,IAAI,CAAC,SAAS;KAC/B,CAAC,CAAC;IACH,cAAc,CAAC,qCAAqC,EAAE,IAAI,CAAC,CAAC;IAC5D,WAAW,CAAC;QACV,MAAM,EAAE,qCAAqC;QAC7C,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,gBAAgB,EAAE,CAAC,yCAAyC,CAAC;KAC9D,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,6EAA6E;AAE7E,gBAAgB;KACb,OAAO,CAAC,sBAAsB,CAAC;KAC/B,WAAW,CAAC,2EAA2E,CAAC;KACxF,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,EAAE;IAClC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,0CAA0C,SAAS,EAAE,CAAC,CAAC;IAC5F,cAAc,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;IAC/C,WAAW,CAAC;QACV,MAAM,EAAE,wBAAwB;QAChC,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,gBAAgB,EAAE,CAAC,oCAAoC,EAAE,yCAAyC,CAAC;KACpG,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,gBAAgB;KACb,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,qCAAqC,CAAC;KAClD,MAAM,CAAC,sBAAsB,EAAE,0CAA0C,EAAE,GAAG,CAAC;KAC/E,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;IAC3E,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,uCAAuC,MAAM,EAAE,CAAC,CAAC;IACtF,cAAc,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;IAC/C,WAAW,CAAC;QACV,MAAM,EAAE,wBAAwB;QAChC,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,gBAAgB,EAAE,CAAC,oCAAoC,EAAE,oCAAoC,CAAC;KAC/F,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,gBAAgB;KACb,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,cAAc,EAAE,kCAAkC,CAAC;KAC1D,MAAM,CAAC,YAAY,EAAE,wBAAwB,CAAC;KAC9C,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,IAAI,IAAI,CAAC,IAAI;QAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,0BAA0B,MAAM,EAAE,CAAC,CAAC;IACzE,cAAc,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;IAC3C,WAAW,CAAC;QACV,MAAM,EAAE,oBAAoB;QAC5B,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,gBAAgB,EAAE,CAAC,yCAAyC,CAAC;KAC9D,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { apiRequest, handleApiError } from "../client.js";
|
|
3
|
+
import { agentOutput } from "../output.js";
|
|
4
|
+
export const crmAppCmd = new Command("crm-app")
|
|
5
|
+
.description("CRM template app — agency pipeline (deals, deliverables, retainers). Distinct from 'naive crm' (vertical-agnostic primitive).")
|
|
6
|
+
.addHelpText("after", `
|
|
7
|
+
Subcommands:
|
|
8
|
+
naive crm-app deals ... Pipeline deals (lead → discovery → proposal → won → active → churned)
|
|
9
|
+
naive crm-app deliverables ... Client deliverables (with optional kanban task mirroring)
|
|
10
|
+
naive crm-app retainers ... Monthly retainers (linked to ext_subscriptions)
|
|
11
|
+
naive crm-app clients Won/active deals grouped by contact + billing-profile MRR/LTV
|
|
12
|
+
naive crm-app summary Aggregate pipeline + MRR + overdue counts
|
|
13
|
+
|
|
14
|
+
Examples:
|
|
15
|
+
$ naive crm-app deals create --title "Acme Q3 implementation" --crm-contact <id>
|
|
16
|
+
$ naive crm-app deals advance <deal-id> --stage proposal
|
|
17
|
+
$ naive crm-app deliverables create --deal <id> --title "Discovery doc" --create-task --assignee delivery-lead
|
|
18
|
+
`);
|
|
19
|
+
// ── Deals ─────────────────────────────────────────────────────────────────
|
|
20
|
+
const dealsCmd = crmAppCmd.command("deals").description("Pipeline deal management");
|
|
21
|
+
dealsCmd
|
|
22
|
+
.command("list")
|
|
23
|
+
.description("List deals")
|
|
24
|
+
.option("--stage <stage>", "Filter by stage (lead|discovery|proposal|won|active|churned)")
|
|
25
|
+
.option("--crm-contact <id>", "Filter by CRM contact")
|
|
26
|
+
.option("--owner <id>", "Filter by owner agent")
|
|
27
|
+
.option("--limit <n>", "Max results (default 50)", "50")
|
|
28
|
+
.option("--offset <n>", "Pagination offset", "0")
|
|
29
|
+
.action(async (opts) => {
|
|
30
|
+
const params = new URLSearchParams({ limit: opts.limit, offset: opts.offset });
|
|
31
|
+
if (opts.stage)
|
|
32
|
+
params.set("stage", opts.stage);
|
|
33
|
+
if (opts.crmContact)
|
|
34
|
+
params.set("crm_contact_id", opts.crmContact);
|
|
35
|
+
if (opts.owner)
|
|
36
|
+
params.set("owner_agent_id", opts.owner);
|
|
37
|
+
const resp = await apiRequest("GET", `/v1/crm-app/deals?${params}`);
|
|
38
|
+
handleApiError("crm-app.deals.list", resp);
|
|
39
|
+
const data = resp.data;
|
|
40
|
+
agentOutput({
|
|
41
|
+
action: "crm-app.deals.list",
|
|
42
|
+
result: resp.data,
|
|
43
|
+
hints: [`${data.count} deal${data.count === 1 ? "" : "s"} returned`],
|
|
44
|
+
next_steps: data.deals.length > 0
|
|
45
|
+
? [{ command: `naive crm-app deals advance ${data.deals[0].id} --stage discovery`, description: "Advance the first deal" }]
|
|
46
|
+
: [{ command: "naive crm-app deals create --title <title> --crm-contact <id>", description: "Create your first deal" }],
|
|
47
|
+
related_commands: ["naive crm-app deals create", "naive crm-app deals advance", "naive crm-app summary"],
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
dealsCmd
|
|
51
|
+
.command("create")
|
|
52
|
+
.description("Create a deal")
|
|
53
|
+
.requiredOption("--title <title>", "Deal name")
|
|
54
|
+
.requiredOption("--crm-contact <id>", "CRM contact UUID")
|
|
55
|
+
.option("--crm-company <id>", "CRM company UUID")
|
|
56
|
+
.option("--template-app-instance <id>", "CRM template app instance UUID")
|
|
57
|
+
.option("--stage <stage>", "Initial stage (default lead)")
|
|
58
|
+
.option("--value-cents <n>", "Deal value in cents")
|
|
59
|
+
.option("--currency <iso>", "ISO currency code")
|
|
60
|
+
.option("--owner <id>", "Owning agent UUID")
|
|
61
|
+
.option("--source <text>", "Where the deal came from")
|
|
62
|
+
.option("--notes <text>", "Free-form notes")
|
|
63
|
+
.action(async (opts) => {
|
|
64
|
+
const resp = await apiRequest("POST", "/v1/crm-app/deals", {
|
|
65
|
+
title: opts.title,
|
|
66
|
+
crm_contact_id: opts.crmContact,
|
|
67
|
+
crm_company_id: opts.crmCompany,
|
|
68
|
+
template_app_instance_id: opts.templateAppInstance,
|
|
69
|
+
stage: opts.stage,
|
|
70
|
+
value_cents: opts.valueCents ? parseInt(opts.valueCents, 10) : undefined,
|
|
71
|
+
currency: opts.currency,
|
|
72
|
+
owner_agent_id: opts.owner,
|
|
73
|
+
source: opts.source,
|
|
74
|
+
notes: opts.notes,
|
|
75
|
+
});
|
|
76
|
+
handleApiError("crm-app.deals.create", resp);
|
|
77
|
+
const data = resp.data;
|
|
78
|
+
agentOutput({
|
|
79
|
+
action: "crm-app.deals.create",
|
|
80
|
+
result: resp.data,
|
|
81
|
+
next_steps: [
|
|
82
|
+
{ command: `naive crm-app deliverables create --deal ${data.deal.id} --title <title>`, description: "Add the first deliverable" },
|
|
83
|
+
{ command: `naive crm-app deals advance ${data.deal.id} --stage discovery`, description: "Advance to discovery once a meeting is booked" },
|
|
84
|
+
],
|
|
85
|
+
related_commands: ["naive crm-app deals advance", "naive crm-app deliverables create"],
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
dealsCmd
|
|
89
|
+
.command("get <deal_id>")
|
|
90
|
+
.description("Get a deal")
|
|
91
|
+
.action(async (dealId) => {
|
|
92
|
+
const resp = await apiRequest("GET", `/v1/crm-app/deals/${dealId}`);
|
|
93
|
+
handleApiError("crm-app.deals.get", resp);
|
|
94
|
+
agentOutput({
|
|
95
|
+
action: "crm-app.deals.get",
|
|
96
|
+
result: resp.data,
|
|
97
|
+
related_commands: ["naive crm-app deals advance", "naive crm-app deliverables list"],
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
dealsCmd
|
|
101
|
+
.command("advance <deal_id>")
|
|
102
|
+
.description("Advance a deal to a new stage")
|
|
103
|
+
.requiredOption("--stage <stage>", "New stage (lead|discovery|proposal|won|active|churned)")
|
|
104
|
+
.option("--notes <text>", "Optional notes about the transition")
|
|
105
|
+
.action(async (dealId, opts) => {
|
|
106
|
+
const resp = await apiRequest("POST", `/v1/crm-app/deals/${dealId}/advance`, {
|
|
107
|
+
stage: opts.stage,
|
|
108
|
+
notes: opts.notes,
|
|
109
|
+
});
|
|
110
|
+
handleApiError("crm-app.deals.advance", resp);
|
|
111
|
+
agentOutput({
|
|
112
|
+
action: "crm-app.deals.advance",
|
|
113
|
+
result: resp.data,
|
|
114
|
+
next_steps: [{ command: `naive crm contacts history <contact_id>`, description: "Verify the transition was logged as an interaction" }],
|
|
115
|
+
related_commands: ["naive crm-app deals list", "naive crm-app summary"],
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
dealsCmd
|
|
119
|
+
.command("update <deal_id>")
|
|
120
|
+
.description("Update deal fields")
|
|
121
|
+
.option("--title <title>")
|
|
122
|
+
.option("--value-cents <n>")
|
|
123
|
+
.option("--notes <text>")
|
|
124
|
+
.action(async (dealId, opts) => {
|
|
125
|
+
const body = {};
|
|
126
|
+
if (opts.title !== undefined)
|
|
127
|
+
body.title = opts.title;
|
|
128
|
+
if (opts.valueCents !== undefined)
|
|
129
|
+
body.value_cents = parseInt(opts.valueCents, 10);
|
|
130
|
+
if (opts.notes !== undefined)
|
|
131
|
+
body.notes = opts.notes;
|
|
132
|
+
const resp = await apiRequest("PATCH", `/v1/crm-app/deals/${dealId}`, body);
|
|
133
|
+
handleApiError("crm-app.deals.update", resp);
|
|
134
|
+
agentOutput({ action: "crm-app.deals.update", result: resp.data, related_commands: ["naive crm-app deals get"] });
|
|
135
|
+
});
|
|
136
|
+
dealsCmd
|
|
137
|
+
.command("delete <deal_id>")
|
|
138
|
+
.description("Delete a deal (cascade)")
|
|
139
|
+
.action(async (dealId) => {
|
|
140
|
+
const resp = await apiRequest("DELETE", `/v1/crm-app/deals/${dealId}`);
|
|
141
|
+
handleApiError("crm-app.deals.delete", resp);
|
|
142
|
+
agentOutput({ action: "crm-app.deals.delete", result: resp.data, related_commands: ["naive crm-app deals list"] });
|
|
143
|
+
});
|
|
144
|
+
// ── Deliverables ─────────────────────────────────────────────────────────
|
|
145
|
+
const deliverablesCmd = crmAppCmd.command("deliverables").description("Client deliverable management");
|
|
146
|
+
deliverablesCmd
|
|
147
|
+
.command("list")
|
|
148
|
+
.description("List deliverables")
|
|
149
|
+
.option("--deal <id>")
|
|
150
|
+
.option("--status <status>", "pending|in_progress|review|done|blocked")
|
|
151
|
+
.option("--owner <id>")
|
|
152
|
+
.option("--limit <n>", "Max results", "50")
|
|
153
|
+
.option("--offset <n>", "Pagination offset", "0")
|
|
154
|
+
.action(async (opts) => {
|
|
155
|
+
const params = new URLSearchParams({ limit: opts.limit, offset: opts.offset });
|
|
156
|
+
if (opts.deal)
|
|
157
|
+
params.set("deal_id", opts.deal);
|
|
158
|
+
if (opts.status)
|
|
159
|
+
params.set("status", opts.status);
|
|
160
|
+
if (opts.owner)
|
|
161
|
+
params.set("owner_agent_id", opts.owner);
|
|
162
|
+
const resp = await apiRequest("GET", `/v1/crm-app/deliverables?${params}`);
|
|
163
|
+
handleApiError("crm-app.deliverables.list", resp);
|
|
164
|
+
const data = resp.data;
|
|
165
|
+
agentOutput({
|
|
166
|
+
action: "crm-app.deliverables.list",
|
|
167
|
+
result: resp.data,
|
|
168
|
+
hints: [`${data.count} deliverable${data.count === 1 ? "" : "s"} returned`],
|
|
169
|
+
related_commands: ["naive crm-app deliverables create", "naive crm-app deliverables update"],
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
deliverablesCmd
|
|
173
|
+
.command("create")
|
|
174
|
+
.description("Create a deliverable")
|
|
175
|
+
.requiredOption("--deal <id>", "Deal UUID")
|
|
176
|
+
.requiredOption("--title <title>", "Deliverable title")
|
|
177
|
+
.option("--description <text>")
|
|
178
|
+
.option("--status <status>", "pending|in_progress|review|done|blocked")
|
|
179
|
+
.option("--due-date <iso>")
|
|
180
|
+
.option("--owner <id>", "Owner agent UUID")
|
|
181
|
+
.option("--create-task", "Mirror as a kanban task (status will auto-sync)")
|
|
182
|
+
.option("--assignee <profile>", "Hermes profile name (when --create-task)")
|
|
183
|
+
.option("--priority <level>", "low|normal|high|critical (when --create-task)")
|
|
184
|
+
.action(async (opts) => {
|
|
185
|
+
const resp = await apiRequest("POST", "/v1/crm-app/deliverables", {
|
|
186
|
+
deal_id: opts.deal,
|
|
187
|
+
title: opts.title,
|
|
188
|
+
description: opts.description,
|
|
189
|
+
status: opts.status,
|
|
190
|
+
due_date: opts.dueDate,
|
|
191
|
+
owner_agent_id: opts.owner,
|
|
192
|
+
create_task: opts.createTask === true,
|
|
193
|
+
assignee: opts.assignee,
|
|
194
|
+
priority: opts.priority,
|
|
195
|
+
});
|
|
196
|
+
handleApiError("crm-app.deliverables.create", resp);
|
|
197
|
+
agentOutput({
|
|
198
|
+
action: "crm-app.deliverables.create",
|
|
199
|
+
result: resp.data,
|
|
200
|
+
next_steps: [{ command: "naive tasks", description: "View the mirrored task on the kanban board" }],
|
|
201
|
+
related_commands: ["naive crm-app deliverables update", "naive tasks"],
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
deliverablesCmd
|
|
205
|
+
.command("update <deliverable_id>")
|
|
206
|
+
.description("Update a deliverable")
|
|
207
|
+
.option("--title <title>")
|
|
208
|
+
.option("--status <status>")
|
|
209
|
+
.option("--due-date <iso>")
|
|
210
|
+
.option("--pct-complete <n>", "0-100")
|
|
211
|
+
.option("--blockers <text>")
|
|
212
|
+
.action(async (deliverableId, opts) => {
|
|
213
|
+
const body = {};
|
|
214
|
+
if (opts.title !== undefined)
|
|
215
|
+
body.title = opts.title;
|
|
216
|
+
if (opts.status !== undefined)
|
|
217
|
+
body.status = opts.status;
|
|
218
|
+
if (opts.dueDate !== undefined)
|
|
219
|
+
body.due_date = opts.dueDate;
|
|
220
|
+
if (opts.pctComplete !== undefined)
|
|
221
|
+
body.pct_complete = parseInt(opts.pctComplete, 10);
|
|
222
|
+
if (opts.blockers !== undefined)
|
|
223
|
+
body.blockers = opts.blockers;
|
|
224
|
+
const resp = await apiRequest("PATCH", `/v1/crm-app/deliverables/${deliverableId}`, body);
|
|
225
|
+
handleApiError("crm-app.deliverables.update", resp);
|
|
226
|
+
agentOutput({ action: "crm-app.deliverables.update", result: resp.data, related_commands: ["naive crm-app deliverables list"] });
|
|
227
|
+
});
|
|
228
|
+
deliverablesCmd
|
|
229
|
+
.command("delete <deliverable_id>")
|
|
230
|
+
.description("Delete a deliverable")
|
|
231
|
+
.action(async (deliverableId) => {
|
|
232
|
+
const resp = await apiRequest("DELETE", `/v1/crm-app/deliverables/${deliverableId}`);
|
|
233
|
+
handleApiError("crm-app.deliverables.delete", resp);
|
|
234
|
+
agentOutput({ action: "crm-app.deliverables.delete", result: resp.data, related_commands: ["naive crm-app deliverables list"] });
|
|
235
|
+
});
|
|
236
|
+
// ── Retainers ────────────────────────────────────────────────────────────
|
|
237
|
+
const retainersCmd = crmAppCmd.command("retainers").description("Retainer management");
|
|
238
|
+
retainersCmd
|
|
239
|
+
.command("list")
|
|
240
|
+
.description("List retainers")
|
|
241
|
+
.option("--deal <id>")
|
|
242
|
+
.option("--status <status>", "active|paused|ended")
|
|
243
|
+
.option("--limit <n>", "Max results", "50")
|
|
244
|
+
.option("--offset <n>", "Pagination offset", "0")
|
|
245
|
+
.action(async (opts) => {
|
|
246
|
+
const params = new URLSearchParams({ limit: opts.limit, offset: opts.offset });
|
|
247
|
+
if (opts.deal)
|
|
248
|
+
params.set("deal_id", opts.deal);
|
|
249
|
+
if (opts.status)
|
|
250
|
+
params.set("status", opts.status);
|
|
251
|
+
const resp = await apiRequest("GET", `/v1/crm-app/retainers?${params}`);
|
|
252
|
+
handleApiError("crm-app.retainers.list", resp);
|
|
253
|
+
agentOutput({ action: "crm-app.retainers.list", result: resp.data, related_commands: ["naive crm-app retainers create"] });
|
|
254
|
+
});
|
|
255
|
+
retainersCmd
|
|
256
|
+
.command("create")
|
|
257
|
+
.description("Create a retainer")
|
|
258
|
+
.requiredOption("--deal <id>", "Deal UUID")
|
|
259
|
+
.requiredOption("--crm-contact <id>", "CRM contact UUID")
|
|
260
|
+
.option("--ext-subscription <id>", "Linked ext_subscription UUID")
|
|
261
|
+
.option("--mrr-cents <n>", "MRR in cents", "0")
|
|
262
|
+
.option("--currency <iso>")
|
|
263
|
+
.action(async (opts) => {
|
|
264
|
+
const resp = await apiRequest("POST", "/v1/crm-app/retainers", {
|
|
265
|
+
deal_id: opts.deal,
|
|
266
|
+
crm_contact_id: opts.crmContact,
|
|
267
|
+
ext_subscription_id: opts.extSubscription,
|
|
268
|
+
mrr_cents: parseInt(opts.mrrCents, 10),
|
|
269
|
+
currency: opts.currency,
|
|
270
|
+
});
|
|
271
|
+
handleApiError("crm-app.retainers.create", resp);
|
|
272
|
+
agentOutput({ action: "crm-app.retainers.create", result: resp.data, related_commands: ["naive crm-app retainers list"] });
|
|
273
|
+
});
|
|
274
|
+
// ── Clients + summary ───────────────────────────────────────────────────
|
|
275
|
+
crmAppCmd
|
|
276
|
+
.command("clients")
|
|
277
|
+
.description("List clients (won/active deals grouped by contact, with billing-profile join)")
|
|
278
|
+
.option("--limit <n>", "Max results", "50")
|
|
279
|
+
.option("--offset <n>", "Pagination offset", "0")
|
|
280
|
+
.action(async (opts) => {
|
|
281
|
+
const params = new URLSearchParams({ limit: opts.limit, offset: opts.offset });
|
|
282
|
+
const resp = await apiRequest("GET", `/v1/crm-app/clients?${params}`);
|
|
283
|
+
handleApiError("crm-app.clients", resp);
|
|
284
|
+
agentOutput({
|
|
285
|
+
action: "crm-app.clients",
|
|
286
|
+
result: resp.data,
|
|
287
|
+
related_commands: ["naive crm-app deliverables list", "naive billing-client subscriptions list"],
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
crmAppCmd
|
|
291
|
+
.command("summary")
|
|
292
|
+
.description("Aggregate pipeline + MRR + overdue counts")
|
|
293
|
+
.option("--template-app-instance <id>")
|
|
294
|
+
.action(async (opts) => {
|
|
295
|
+
const params = new URLSearchParams();
|
|
296
|
+
if (opts.templateAppInstance)
|
|
297
|
+
params.set("template_app_instance_id", opts.templateAppInstance);
|
|
298
|
+
const resp = await apiRequest("GET", `/v1/crm-app/summary?${params}`);
|
|
299
|
+
handleApiError("crm-app.summary", resp);
|
|
300
|
+
agentOutput({
|
|
301
|
+
action: "crm-app.summary",
|
|
302
|
+
result: resp.data,
|
|
303
|
+
related_commands: ["naive crm-app deals list", "naive billing-client mrr"],
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
//# sourceMappingURL=crm-app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crm-app.js","sourceRoot":"","sources":["../../src/commands/crm-app.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { apiRequest, handleApiError } from "../client.js";
|
|
3
|
+
import { agentOutput } from "../output.js";
|
|
4
|
+
export const crmCmd = new Command("crm")
|
|
5
|
+
.description("naive/crm primitive — contacts, companies, and interaction history")
|
|
6
|
+
.addHelpText("after", `
|
|
7
|
+
Subcommands:
|
|
8
|
+
naive crm contacts ... Manage CRM contacts (create, list, find, get, update, merge, log, history)
|
|
9
|
+
naive crm companies ... Manage CRM companies (external organizations)
|
|
10
|
+
|
|
11
|
+
The CRM primitive is the vertical-agnostic identity graph. Pipelines/deals
|
|
12
|
+
live in the CRM template app (naive crm-app). Use this primitive any time
|
|
13
|
+
an agent needs to:
|
|
14
|
+
- Look up a contact before sending email (dedupe by email/phone)
|
|
15
|
+
- Log activity history on a contact (calls, notes, payments)
|
|
16
|
+
- Find or create external companies (clients, prospects)
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
$ naive crm contacts find --email lead@example.com
|
|
20
|
+
$ naive crm contacts create --name "Jane Smith" --email jane@acme.com --company Acme
|
|
21
|
+
$ naive crm contacts log-interaction <contact-id> --type note --content "Discovery call went well"
|
|
22
|
+
$ naive crm contacts history <contact-id> --limit 20
|
|
23
|
+
`);
|
|
24
|
+
// ── Contacts ──────────────────────────────────────────────────────────────
|
|
25
|
+
const contactsCmd = crmCmd.command("contacts").description("CRM contact management");
|
|
26
|
+
contactsCmd
|
|
27
|
+
.command("list")
|
|
28
|
+
.description("List CRM contacts")
|
|
29
|
+
.option("--search <term>", "Free-text search on name and emails")
|
|
30
|
+
.option("--crm-company <id>", "Filter to a specific CRM company")
|
|
31
|
+
.option("--sort <field>", "Sort field: created_at | name", "created_at")
|
|
32
|
+
.option("--limit <n>", "Max results (default 50, max 200)", "50")
|
|
33
|
+
.option("--offset <n>", "Pagination offset", "0")
|
|
34
|
+
.action(async (opts) => {
|
|
35
|
+
const params = new URLSearchParams({ limit: opts.limit, offset: opts.offset, sort: opts.sort });
|
|
36
|
+
if (opts.search)
|
|
37
|
+
params.set("search", opts.search);
|
|
38
|
+
if (opts.crmCompany)
|
|
39
|
+
params.set("crm_company_id", opts.crmCompany);
|
|
40
|
+
const resp = await apiRequest("GET", `/v1/crm/contacts?${params}`);
|
|
41
|
+
handleApiError("crm.contacts.list", resp);
|
|
42
|
+
const data = resp.data;
|
|
43
|
+
agentOutput({
|
|
44
|
+
action: "crm.contacts.list",
|
|
45
|
+
result: resp.data,
|
|
46
|
+
next_steps: [
|
|
47
|
+
...(data.contacts.length > 0
|
|
48
|
+
? [{ command: `naive crm contacts get ${data.contacts[0].id}`, description: "Inspect the first contact" }]
|
|
49
|
+
: [{ command: "naive crm contacts create --name <name> --email <email>", description: "Create your first contact" }]),
|
|
50
|
+
{ command: "naive crm contacts find --email <email>", description: "Find a contact by email before creating to dedupe" },
|
|
51
|
+
],
|
|
52
|
+
hints: [`${data.count} contact${data.count === 1 ? "" : "s"} returned`],
|
|
53
|
+
related_commands: ["naive crm contacts create", "naive crm contacts find", "naive crm contacts get"],
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
contactsCmd
|
|
57
|
+
.command("create")
|
|
58
|
+
.description("Create a CRM contact (idempotent on email/phone)")
|
|
59
|
+
.option("--name <name>", "Contact full name")
|
|
60
|
+
.option("--email <email>", "Primary email address")
|
|
61
|
+
.option("--phone <phone>", "Primary phone number")
|
|
62
|
+
.option("--company <name>", "Company name (auto-creates if no --crm-company-id is provided)")
|
|
63
|
+
.option("--crm-company-id <id>", "Existing CRM company UUID to link to")
|
|
64
|
+
.option("--source <source>", "Where this contact came from")
|
|
65
|
+
.action(async (opts) => {
|
|
66
|
+
const resp = await apiRequest("POST", "/v1/crm/contacts", {
|
|
67
|
+
name: opts.name,
|
|
68
|
+
email: opts.email,
|
|
69
|
+
phone: opts.phone,
|
|
70
|
+
company: opts.company,
|
|
71
|
+
crm_company_id: opts.crmCompanyId,
|
|
72
|
+
source: opts.source,
|
|
73
|
+
});
|
|
74
|
+
handleApiError("crm.contacts.create", resp);
|
|
75
|
+
const data = resp.data;
|
|
76
|
+
agentOutput({
|
|
77
|
+
action: "crm.contacts.create",
|
|
78
|
+
result: resp.data,
|
|
79
|
+
next_steps: [
|
|
80
|
+
{ command: `naive crm contacts log-interaction ${data.contact.id} --type note --content "..."`, description: "Log activity on this contact" },
|
|
81
|
+
{ command: `naive crm contacts history ${data.contact.id}`, description: "View full activity history" },
|
|
82
|
+
],
|
|
83
|
+
hints: [
|
|
84
|
+
data.created ? "Created new contact" : "Returned existing contact (matched by email/phone)",
|
|
85
|
+
`Contact ID: ${data.contact.id}`,
|
|
86
|
+
],
|
|
87
|
+
related_commands: ["naive crm contacts find", "naive crm contacts log-interaction"],
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
contactsCmd
|
|
91
|
+
.command("find")
|
|
92
|
+
.description("Find a contact by email, phone, or fuzzy name match — use this BEFORE creating to dedupe")
|
|
93
|
+
.option("--email <email>", "Exact match (case-insensitive)")
|
|
94
|
+
.option("--phone <phone>", "Exact match (digits-only)")
|
|
95
|
+
.option("--name <name>", "Fuzzy match (trigram)")
|
|
96
|
+
.option("--limit <n>", "Max results (default 10, max 50)", "10")
|
|
97
|
+
.action(async (opts) => {
|
|
98
|
+
const resp = await apiRequest("POST", "/v1/crm/contacts/find", {
|
|
99
|
+
email: opts.email,
|
|
100
|
+
phone: opts.phone,
|
|
101
|
+
name: opts.name,
|
|
102
|
+
limit: parseInt(opts.limit, 10),
|
|
103
|
+
});
|
|
104
|
+
handleApiError("crm.contacts.find", resp);
|
|
105
|
+
const data = resp.data;
|
|
106
|
+
agentOutput({
|
|
107
|
+
action: "crm.contacts.find",
|
|
108
|
+
result: resp.data,
|
|
109
|
+
next_steps: data.contacts.length > 0
|
|
110
|
+
? [
|
|
111
|
+
{ command: `naive crm contacts get ${data.contacts[0].id}`, description: "Get full contact details" },
|
|
112
|
+
{ command: `naive crm contacts log-interaction ${data.contacts[0].id} --type note --content "..."`, description: "Log activity on this contact" },
|
|
113
|
+
]
|
|
114
|
+
: [{ command: "naive crm contacts create --name <name> --email <email>", description: "Create a new contact" }],
|
|
115
|
+
hints: [
|
|
116
|
+
data.contacts.length === 0 ? "No match — safe to create a new contact" : `Match type: ${data.match_type}`,
|
|
117
|
+
],
|
|
118
|
+
related_commands: ["naive crm contacts create", "naive crm contacts merge"],
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
contactsCmd
|
|
122
|
+
.command("get <contact_id>")
|
|
123
|
+
.description("Get full contact details")
|
|
124
|
+
.action(async (contactId) => {
|
|
125
|
+
const resp = await apiRequest("GET", `/v1/crm/contacts/${contactId}`);
|
|
126
|
+
handleApiError("crm.contacts.get", resp);
|
|
127
|
+
agentOutput({
|
|
128
|
+
action: "crm.contacts.get",
|
|
129
|
+
result: resp.data,
|
|
130
|
+
next_steps: [
|
|
131
|
+
{ command: `naive crm contacts history ${contactId}`, description: "View interaction history" },
|
|
132
|
+
{ command: `naive crm contacts update ${contactId} --name <name>`, description: "Update contact" },
|
|
133
|
+
],
|
|
134
|
+
related_commands: ["naive crm contacts history", "naive crm contacts update"],
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
contactsCmd
|
|
138
|
+
.command("update <contact_id>")
|
|
139
|
+
.description("Update a contact")
|
|
140
|
+
.option("--name <name>", "New name")
|
|
141
|
+
.option("--emails <list>", "Comma-separated list of emails (replaces existing)")
|
|
142
|
+
.option("--phones <list>", "Comma-separated list of phones (replaces existing)")
|
|
143
|
+
.option("--crm-company-id <id>", "Link to a CRM company (use 'null' to clear)")
|
|
144
|
+
.action(async (contactId, opts) => {
|
|
145
|
+
const body = {};
|
|
146
|
+
if (opts.name !== undefined)
|
|
147
|
+
body.name = opts.name;
|
|
148
|
+
if (opts.emails !== undefined)
|
|
149
|
+
body.emails = opts.emails.split(",").map((s) => s.trim()).filter(Boolean);
|
|
150
|
+
if (opts.phones !== undefined)
|
|
151
|
+
body.phones = opts.phones.split(",").map((s) => s.trim()).filter(Boolean);
|
|
152
|
+
if (opts.crmCompanyId !== undefined)
|
|
153
|
+
body.crm_company_id = opts.crmCompanyId === "null" ? null : opts.crmCompanyId;
|
|
154
|
+
const resp = await apiRequest("PATCH", `/v1/crm/contacts/${contactId}`, body);
|
|
155
|
+
handleApiError("crm.contacts.update", resp);
|
|
156
|
+
agentOutput({
|
|
157
|
+
action: "crm.contacts.update",
|
|
158
|
+
result: resp.data,
|
|
159
|
+
next_steps: [{ command: `naive crm contacts get ${contactId}`, description: "Verify the update" }],
|
|
160
|
+
related_commands: ["naive crm contacts get", "naive crm contacts history"],
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
contactsCmd
|
|
164
|
+
.command("delete <contact_id>")
|
|
165
|
+
.description("Delete a CRM contact (cascade-deletes interactions)")
|
|
166
|
+
.action(async (contactId) => {
|
|
167
|
+
const resp = await apiRequest("DELETE", `/v1/crm/contacts/${contactId}`);
|
|
168
|
+
handleApiError("crm.contacts.delete", resp);
|
|
169
|
+
agentOutput({
|
|
170
|
+
action: "crm.contacts.delete",
|
|
171
|
+
result: resp.data,
|
|
172
|
+
next_steps: [{ command: "naive crm contacts list", description: "Verify removal" }],
|
|
173
|
+
related_commands: ["naive crm contacts list"],
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
contactsCmd
|
|
177
|
+
.command("merge <primary_id>")
|
|
178
|
+
.description("Merge a duplicate contact into the primary contact")
|
|
179
|
+
.requiredOption("--duplicate <id>", "The duplicate contact ID to merge into the primary")
|
|
180
|
+
.action(async (primaryId, opts) => {
|
|
181
|
+
const resp = await apiRequest("POST", `/v1/crm/contacts/${primaryId}/merge`, {
|
|
182
|
+
duplicate_id: opts.duplicate,
|
|
183
|
+
});
|
|
184
|
+
handleApiError("crm.contacts.merge", resp);
|
|
185
|
+
agentOutput({
|
|
186
|
+
action: "crm.contacts.merge",
|
|
187
|
+
result: resp.data,
|
|
188
|
+
next_steps: [{ command: `naive crm contacts get ${primaryId}`, description: "Inspect the merged contact" }],
|
|
189
|
+
hints: ["All interactions moved to primary, duplicate deleted"],
|
|
190
|
+
related_commands: ["naive crm contacts get", "naive crm contacts history"],
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
contactsCmd
|
|
194
|
+
.command("log-interaction <contact_id>")
|
|
195
|
+
.description("Log an interaction (email | call | note | task | payment) on a contact")
|
|
196
|
+
.requiredOption("--type <type>", "email | call | note | task | payment")
|
|
197
|
+
.option("--direction <dir>", "inbound | outbound | internal", "internal")
|
|
198
|
+
.option("--content <text>", "Free-text body")
|
|
199
|
+
.option("--refs <json>", "Cross-references as JSON, e.g. '{\"message_id\":\"abc\"}'")
|
|
200
|
+
.option("--occurred-at <iso>", "ISO timestamp; defaults to now")
|
|
201
|
+
.action(async (contactId, opts) => {
|
|
202
|
+
const body = {
|
|
203
|
+
type: opts.type,
|
|
204
|
+
direction: opts.direction,
|
|
205
|
+
};
|
|
206
|
+
if (opts.content !== undefined)
|
|
207
|
+
body.content = opts.content;
|
|
208
|
+
if (opts.refs !== undefined) {
|
|
209
|
+
try {
|
|
210
|
+
body.refs = JSON.parse(opts.refs);
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
agentOutput({
|
|
214
|
+
action: "crm.contacts.log-interaction",
|
|
215
|
+
result: { error: "invalid_input", message: "--refs must be valid JSON" },
|
|
216
|
+
hints: ["Wrap in single quotes: --refs '{\"key\":\"value\"}'"],
|
|
217
|
+
related_commands: ["naive crm contacts log-interaction"],
|
|
218
|
+
});
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (opts.occurredAt !== undefined)
|
|
223
|
+
body.occurred_at = opts.occurredAt;
|
|
224
|
+
const resp = await apiRequest("POST", `/v1/crm/contacts/${contactId}/interactions`, body);
|
|
225
|
+
handleApiError("crm.contacts.log-interaction", resp);
|
|
226
|
+
agentOutput({
|
|
227
|
+
action: "crm.contacts.log-interaction",
|
|
228
|
+
result: resp.data,
|
|
229
|
+
next_steps: [{ command: `naive crm contacts history ${contactId}`, description: "View updated history" }],
|
|
230
|
+
related_commands: ["naive crm contacts history", "naive crm contacts get"],
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
contactsCmd
|
|
234
|
+
.command("history <contact_id>")
|
|
235
|
+
.description("Get interaction history (most recent first)")
|
|
236
|
+
.option("--types <list>", "Comma-separated types to filter: email,call,note,task,payment")
|
|
237
|
+
.option("--since <iso>", "Lower bound ISO timestamp")
|
|
238
|
+
.option("--until <iso>", "Upper bound ISO timestamp")
|
|
239
|
+
.option("--limit <n>", "Max results (default 50, max 200)", "50")
|
|
240
|
+
.option("--offset <n>", "Pagination offset", "0")
|
|
241
|
+
.action(async (contactId, opts) => {
|
|
242
|
+
const params = new URLSearchParams({ limit: opts.limit, offset: opts.offset });
|
|
243
|
+
if (opts.types)
|
|
244
|
+
params.set("types", opts.types);
|
|
245
|
+
if (opts.since)
|
|
246
|
+
params.set("since", opts.since);
|
|
247
|
+
if (opts.until)
|
|
248
|
+
params.set("until", opts.until);
|
|
249
|
+
const resp = await apiRequest("GET", `/v1/crm/contacts/${contactId}/interactions?${params}`);
|
|
250
|
+
handleApiError("crm.contacts.history", resp);
|
|
251
|
+
const data = resp.data;
|
|
252
|
+
agentOutput({
|
|
253
|
+
action: "crm.contacts.history",
|
|
254
|
+
result: resp.data,
|
|
255
|
+
hints: [`${data.count} interaction${data.count === 1 ? "" : "s"} returned`],
|
|
256
|
+
next_steps: [{ command: `naive crm contacts log-interaction ${contactId} --type note --content "..."`, description: "Log a new interaction" }],
|
|
257
|
+
related_commands: ["naive crm contacts log-interaction", "naive crm contacts get"],
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
// ── Companies ────────────────────────────────────────────────────────────
|
|
261
|
+
const companiesSubCmd = crmCmd.command("companies").description("CRM company (external organization) management");
|
|
262
|
+
companiesSubCmd
|
|
263
|
+
.command("list")
|
|
264
|
+
.description("List CRM companies")
|
|
265
|
+
.option("--search <term>", "Free-text search on name/domain")
|
|
266
|
+
.option("--limit <n>", "Max results (default 50, max 200)", "50")
|
|
267
|
+
.option("--offset <n>", "Pagination offset", "0")
|
|
268
|
+
.action(async (opts) => {
|
|
269
|
+
const params = new URLSearchParams({ limit: opts.limit, offset: opts.offset });
|
|
270
|
+
if (opts.search)
|
|
271
|
+
params.set("search", opts.search);
|
|
272
|
+
const resp = await apiRequest("GET", `/v1/crm/companies?${params}`);
|
|
273
|
+
handleApiError("crm.companies.list", resp);
|
|
274
|
+
const data = resp.data;
|
|
275
|
+
agentOutput({
|
|
276
|
+
action: "crm.companies.list",
|
|
277
|
+
result: resp.data,
|
|
278
|
+
hints: [`${data.count} compan${data.count === 1 ? "y" : "ies"} returned`],
|
|
279
|
+
next_steps: [{ command: "naive crm companies create --name <name> --domain <domain>", description: "Create a new CRM company" }],
|
|
280
|
+
related_commands: ["naive crm companies create", "naive crm companies get"],
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
companiesSubCmd
|
|
284
|
+
.command("create")
|
|
285
|
+
.description("Create a CRM company (idempotent on lower(domain))")
|
|
286
|
+
.requiredOption("--name <name>", "Company name")
|
|
287
|
+
.option("--domain <domain>", "Primary web domain (e.g. acme.com)")
|
|
288
|
+
.option("--source <source>", "Where this record came from")
|
|
289
|
+
.action(async (opts) => {
|
|
290
|
+
const resp = await apiRequest("POST", "/v1/crm/companies", {
|
|
291
|
+
name: opts.name,
|
|
292
|
+
domain: opts.domain,
|
|
293
|
+
source: opts.source,
|
|
294
|
+
});
|
|
295
|
+
handleApiError("crm.companies.create", resp);
|
|
296
|
+
const data = resp.data;
|
|
297
|
+
agentOutput({
|
|
298
|
+
action: "crm.companies.create",
|
|
299
|
+
result: resp.data,
|
|
300
|
+
hints: [data.created ? "Created new company" : "Returned existing company (matched by domain)"],
|
|
301
|
+
next_steps: [
|
|
302
|
+
{ command: `naive crm contacts create --crm-company-id ${data.company.id} --name <name> --email <email>`, description: "Link a contact to this company" },
|
|
303
|
+
],
|
|
304
|
+
related_commands: ["naive crm contacts create", "naive crm companies get"],
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
companiesSubCmd
|
|
308
|
+
.command("get <company_id>")
|
|
309
|
+
.description("Get CRM company details")
|
|
310
|
+
.action(async (companyId) => {
|
|
311
|
+
const resp = await apiRequest("GET", `/v1/crm/companies/${companyId}`);
|
|
312
|
+
handleApiError("crm.companies.get", resp);
|
|
313
|
+
agentOutput({
|
|
314
|
+
action: "crm.companies.get",
|
|
315
|
+
result: resp.data,
|
|
316
|
+
related_commands: ["naive crm companies list", "naive crm contacts list"],
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
//# sourceMappingURL=crm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crm.js","sourceRoot":"","sources":["../../src/commands/crm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { apiRequest, handleApiError } from "../client.js";
|
|
3
|
+
import { agentOutput } from "../output.js";
|
|
4
|
+
export const integrationsCmd = new Command("integrations")
|
|
5
|
+
.alias("integration")
|
|
6
|
+
.description("3rd-party integrations — connect 250+ Composio toolkits (Gmail, GitHub, Linear, Notion, ...) and invoke their tools")
|
|
7
|
+
.addHelpText("after", `
|
|
8
|
+
Subcommands:
|
|
9
|
+
naive integrations list List toolkits + connection state
|
|
10
|
+
naive integrations connected List only connected toolkits
|
|
11
|
+
naive integrations connect <toolkit> Start OAuth/API-key flow → returns a redirect URL
|
|
12
|
+
naive integrations disconnect <toolkit> [--purge] Disable (default) or permanently delete connection
|
|
13
|
+
naive integrations tools <toolkit> List the tools exposed by a toolkit
|
|
14
|
+
naive integrations execute <toolkit> <tool> [--args] Invoke a Composio tool (costs 1 credit on success)
|
|
15
|
+
|
|
16
|
+
Common Toolkits:
|
|
17
|
+
gmail, googlecalendar, googledrive, github, linear, notion, slack,
|
|
18
|
+
airtable, hubspot, salesforce, stripe, shopify, calendly, twilio, zoom
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
$ naive integrations connect gmail
|
|
22
|
+
# Open the redirect_url, finish OAuth, then:
|
|
23
|
+
$ naive integrations execute gmail GMAIL_SEND_EMAIL \\
|
|
24
|
+
--args '{"recipient_email":"me@example.com","subject":"hi","body":"hello"}'
|
|
25
|
+
|
|
26
|
+
Cost:
|
|
27
|
+
- listing toolkits / tools / connecting / disconnecting: free
|
|
28
|
+
- executing a tool: 1 credit per successful call
|
|
29
|
+
`);
|
|
30
|
+
integrationsCmd
|
|
31
|
+
.command("list")
|
|
32
|
+
.description("List 3rd-party toolkits available via Composio (paged)")
|
|
33
|
+
.option("--search <q>", "Filter by name or slug substring")
|
|
34
|
+
.option("--cursor <c>", "Opaque cursor from previous response")
|
|
35
|
+
.option("--limit <n>", "Page size (max 50)")
|
|
36
|
+
.option("--connected", "Only show connected toolkits")
|
|
37
|
+
.action(async (opts) => {
|
|
38
|
+
const params = new URLSearchParams();
|
|
39
|
+
if (opts.search)
|
|
40
|
+
params.set("search", opts.search);
|
|
41
|
+
if (opts.cursor)
|
|
42
|
+
params.set("cursor", opts.cursor);
|
|
43
|
+
if (opts.limit)
|
|
44
|
+
params.set("limit", opts.limit);
|
|
45
|
+
if (opts.connected)
|
|
46
|
+
params.set("connected", "true");
|
|
47
|
+
const qs = params.toString();
|
|
48
|
+
const resp = await apiRequest("GET", `/v1/integrations${qs ? `?${qs}` : ""}`);
|
|
49
|
+
handleApiError("integrations.list", resp);
|
|
50
|
+
const data = resp.data;
|
|
51
|
+
agentOutput({
|
|
52
|
+
action: "integrations.list",
|
|
53
|
+
result: resp.data,
|
|
54
|
+
next_steps: [
|
|
55
|
+
{ command: "naive integrations connect <toolkit>", description: "Connect a toolkit by slug" },
|
|
56
|
+
...(data.nextCursor
|
|
57
|
+
? [{ command: `naive integrations list --cursor ${data.nextCursor}`, description: "Fetch the next page" }]
|
|
58
|
+
: []),
|
|
59
|
+
],
|
|
60
|
+
hints: [`${data.toolkits?.length ?? 0} toolkit(s) on this page`],
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
integrationsCmd
|
|
64
|
+
.command("connected")
|
|
65
|
+
.description("List only the toolkits this company has connected")
|
|
66
|
+
.option("--cursor <c>", "Opaque cursor from previous response")
|
|
67
|
+
.option("--limit <n>", "Page size (max 50)")
|
|
68
|
+
.action(async (opts) => {
|
|
69
|
+
const params = new URLSearchParams();
|
|
70
|
+
if (opts.cursor)
|
|
71
|
+
params.set("cursor", opts.cursor);
|
|
72
|
+
if (opts.limit)
|
|
73
|
+
params.set("limit", opts.limit);
|
|
74
|
+
const qs = params.toString();
|
|
75
|
+
const resp = await apiRequest("GET", `/v1/integrations/connected${qs ? `?${qs}` : ""}`);
|
|
76
|
+
handleApiError("integrations.connected", resp);
|
|
77
|
+
const data = resp.data;
|
|
78
|
+
agentOutput({
|
|
79
|
+
action: "integrations.connected",
|
|
80
|
+
result: resp.data,
|
|
81
|
+
next_steps: [
|
|
82
|
+
{ command: "naive integrations tools <toolkit>", description: "Inspect a connected toolkit's tools" },
|
|
83
|
+
{ command: "naive integrations execute <toolkit> <tool>", description: "Invoke a tool" },
|
|
84
|
+
],
|
|
85
|
+
hints: [`${data.toolkits?.length ?? 0} connected toolkit(s)`],
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
integrationsCmd
|
|
89
|
+
.command("connect <toolkit>")
|
|
90
|
+
.description("Start an OAuth/API-key flow for a toolkit (returns a redirect URL)")
|
|
91
|
+
.option("--callback-url <url>", "Where Composio should send the user back after auth")
|
|
92
|
+
.action(async (toolkit, opts) => {
|
|
93
|
+
const body = { toolkit };
|
|
94
|
+
if (opts.callbackUrl)
|
|
95
|
+
body.callback_url = opts.callbackUrl;
|
|
96
|
+
const resp = await apiRequest("POST", "/v1/integrations/connect", body);
|
|
97
|
+
handleApiError("integrations.connect", resp);
|
|
98
|
+
const data = resp.data;
|
|
99
|
+
agentOutput({
|
|
100
|
+
action: "integrations.connect",
|
|
101
|
+
result: resp.data,
|
|
102
|
+
next_steps: [
|
|
103
|
+
{ command: `naive integrations connected`, description: "Check connection status after finishing in-browser" },
|
|
104
|
+
{ command: `naive integrations tools ${toolkit}`, description: "List tools once the connection is ACTIVE" },
|
|
105
|
+
],
|
|
106
|
+
hints: [
|
|
107
|
+
data.redirectUrl
|
|
108
|
+
? `Open this URL to finish connecting ${toolkit}:`
|
|
109
|
+
: `Connection initiated for ${toolkit} (no redirect needed — credentials supplied via API).`,
|
|
110
|
+
...(data.redirectUrl ? [data.redirectUrl] : []),
|
|
111
|
+
`connected_account_id: ${data.connectedAccountId} · status: ${data.status}`,
|
|
112
|
+
],
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
integrationsCmd
|
|
116
|
+
.command("disconnect <toolkit>")
|
|
117
|
+
.description("Disconnect a toolkit (soft-disable by default; --purge for permanent delete)")
|
|
118
|
+
.option("--purge", "Permanently delete the connection and revoke tokens")
|
|
119
|
+
.action(async (toolkit, opts) => {
|
|
120
|
+
const qs = opts.purge ? "?purge=true" : "";
|
|
121
|
+
const resp = await apiRequest("DELETE", `/v1/integrations/${encodeURIComponent(toolkit)}${qs}`);
|
|
122
|
+
handleApiError("integrations.disconnect", resp);
|
|
123
|
+
agentOutput({
|
|
124
|
+
action: "integrations.disconnect",
|
|
125
|
+
result: resp.data,
|
|
126
|
+
next_steps: [
|
|
127
|
+
{ command: `naive integrations connect ${toolkit}`, description: "Reconnect this toolkit later" },
|
|
128
|
+
{ command: "naive integrations connected", description: "List remaining connected toolkits" },
|
|
129
|
+
],
|
|
130
|
+
hints: [opts.purge ? `Toolkit ${toolkit} permanently deleted.` : `Toolkit ${toolkit} disabled (reversible).`],
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
integrationsCmd
|
|
134
|
+
.command("tools <toolkit>")
|
|
135
|
+
.description("List the individual tools exposed by a toolkit")
|
|
136
|
+
.option("--search <q>", "Semantic search across tool descriptions")
|
|
137
|
+
.option("--limit <n>", "Max tools to return (default 100, max 200)")
|
|
138
|
+
.action(async (toolkit, opts) => {
|
|
139
|
+
const params = new URLSearchParams();
|
|
140
|
+
if (opts.search)
|
|
141
|
+
params.set("search", opts.search);
|
|
142
|
+
if (opts.limit)
|
|
143
|
+
params.set("limit", opts.limit);
|
|
144
|
+
const qs = params.toString();
|
|
145
|
+
const resp = await apiRequest("GET", `/v1/integrations/${encodeURIComponent(toolkit)}/tools${qs ? `?${qs}` : ""}`);
|
|
146
|
+
handleApiError("integrations.tools", resp);
|
|
147
|
+
const data = resp.data;
|
|
148
|
+
agentOutput({
|
|
149
|
+
action: "integrations.tools",
|
|
150
|
+
result: resp.data,
|
|
151
|
+
next_steps: [
|
|
152
|
+
{ command: `naive integrations execute ${toolkit} <tool>`, description: "Invoke one of these tools" },
|
|
153
|
+
],
|
|
154
|
+
hints: [`${data.tools?.length ?? 0} tool(s) returned for ${toolkit}`],
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
integrationsCmd
|
|
158
|
+
.command("execute <toolkit> <tool>")
|
|
159
|
+
.description("Invoke a Composio tool. Costs 1 credit on success.")
|
|
160
|
+
.option("--args <json>", "Tool arguments as JSON object", "{}")
|
|
161
|
+
.option("--connected-account-id <id>", "Override which connected account to use")
|
|
162
|
+
.action(async (toolkit, tool, opts) => {
|
|
163
|
+
let args = {};
|
|
164
|
+
try {
|
|
165
|
+
args = JSON.parse(opts.args ?? "{}");
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
console.error(JSON.stringify({
|
|
169
|
+
success: false,
|
|
170
|
+
action: "integrations.execute",
|
|
171
|
+
error: { code: "invalid_input", message: `--args must be valid JSON: ${err.message}` },
|
|
172
|
+
recovery_steps: [
|
|
173
|
+
{ command: `naive integrations execute ${toolkit} ${tool} --args '{"key":"value"}'`, description: "Retry with valid JSON" },
|
|
174
|
+
],
|
|
175
|
+
}, null, 2));
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
const body = { tool, arguments: args };
|
|
179
|
+
if (opts.connectedAccountId)
|
|
180
|
+
body.connected_account_id = opts.connectedAccountId;
|
|
181
|
+
const resp = await apiRequest("POST", `/v1/integrations/${encodeURIComponent(toolkit)}/execute`, body);
|
|
182
|
+
handleApiError("integrations.execute", resp);
|
|
183
|
+
const data = resp.data;
|
|
184
|
+
const credits = typeof data.creditsRemaining === "number" ? data.creditsRemaining.toFixed(2) : "?";
|
|
185
|
+
agentOutput({
|
|
186
|
+
action: "integrations.execute",
|
|
187
|
+
result: resp.data,
|
|
188
|
+
next_steps: data.successful
|
|
189
|
+
? [{ command: `naive integrations tools ${toolkit}`, description: "Discover related tools" }]
|
|
190
|
+
: [
|
|
191
|
+
{ command: `naive integrations connected`, description: "Confirm the toolkit is connected" },
|
|
192
|
+
{ command: `naive integrations connect ${toolkit}`, description: "Reconnect if the auth lapsed" },
|
|
193
|
+
],
|
|
194
|
+
hints: data.successful
|
|
195
|
+
? [`Executed ${tool} successfully. Credits remaining: ${credits}.`]
|
|
196
|
+
: [`Tool returned an error: ${data.error ?? "unknown"}`],
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
//# sourceMappingURL=integrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../src/commands/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,OAAO,CAAC,cAAc,CAAC;KACvD,KAAK,CAAC,aAAa,CAAC;KACpB,WAAW,CAAC,qHAAqH,CAAC;KAClI,WAAW,CAAC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;CAsBvB,CAAC,CAAC;AAEH,eAAe;KACZ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,wDAAwD,CAAC;KACrE,MAAM,CAAC,cAAc,EAAE,kCAAkC,CAAC;KAC1D,MAAM,CAAC,cAAc,EAAE,sCAAsC,CAAC;KAC9D,MAAM,CAAC,aAAa,EAAE,oBAAoB,CAAC;KAC3C,MAAM,CAAC,aAAa,EAAE,8BAA8B,CAAC;KACrD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,IAAI,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,IAAI,CAAC,SAAS;QAAE,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACpD,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9E,cAAc,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAsD,CAAC;IACzE,WAAW,CAAC;QACV,MAAM,EAAE,mBAAmB;QAC3B,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,UAAU,EAAE;YACV,EAAE,OAAO,EAAE,sCAAsC,EAAE,WAAW,EAAE,2BAA2B,EAAE;YAC7F,GAAG,CAAC,IAAI,CAAC,UAAU;gBACjB,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,oCAAoC,IAAI,CAAC,UAAU,EAAE,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;gBAC1G,CAAC,CAAC,EAAE,CAAC;SACR;QACD,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,0BAA0B,CAAC;KACjE,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,eAAe;KACZ,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CAAC,mDAAmD,CAAC;KAChE,MAAM,CAAC,cAAc,EAAE,sCAAsC,CAAC;KAC9D,MAAM,CAAC,aAAa,EAAE,oBAAoB,CAAC;KAC3C,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,IAAI,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,6BAA6B,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxF,cAAc,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAA2B,CAAC;IAC9C,WAAW,CAAC;QACV,MAAM,EAAE,wBAAwB;QAChC,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,UAAU,EAAE;YACV,EAAE,OAAO,EAAE,oCAAoC,EAAE,WAAW,EAAE,qCAAqC,EAAE;YACrG,EAAE,OAAO,EAAE,6CAA6C,EAAE,WAAW,EAAE,eAAe,EAAE;SACzF;QACD,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,uBAAuB,CAAC;KAC9D,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,eAAe;KACZ,OAAO,CAAC,mBAAmB,CAAC;KAC5B,WAAW,CAAC,oEAAoE,CAAC;KACjF,MAAM,CAAC,sBAAsB,EAAE,qDAAqD,CAAC;KACrF,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAI,EAAE,EAAE;IACtC,MAAM,IAAI,GAA4B,EAAE,OAAO,EAAE,CAAC;IAClD,IAAI,IAAI,CAAC,WAAW;QAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC;IAC3D,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,0BAA0B,EAAE,IAAI,CAAC,CAAC;IACxE,cAAc,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAkF,CAAC;IACrG,WAAW,CAAC;QACV,MAAM,EAAE,sBAAsB;QAC9B,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,UAAU,EAAE;YACV,EAAE,OAAO,EAAE,8BAA8B,EAAE,WAAW,EAAE,oDAAoD,EAAE;YAC9G,EAAE,OAAO,EAAE,4BAA4B,OAAO,EAAE,EAAE,WAAW,EAAE,0CAA0C,EAAE;SAC5G;QACD,KAAK,EAAE;YACL,IAAI,CAAC,WAAW;gBACd,CAAC,CAAC,sCAAsC,OAAO,GAAG;gBAClD,CAAC,CAAC,4BAA4B,OAAO,uDAAuD;YAC9F,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,yBAAyB,IAAI,CAAC,kBAAkB,cAAc,IAAI,CAAC,MAAM,EAAE;SAC5E;KACF,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,eAAe;KACZ,OAAO,CAAC,sBAAsB,CAAC;KAC/B,WAAW,CAAC,8EAA8E,CAAC;KAC3F,MAAM,CAAC,SAAS,EAAE,qDAAqD,CAAC;KACxE,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAI,EAAE,EAAE;IACtC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3C,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,QAAQ,EAAE,oBAAoB,kBAAkB,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAChG,cAAc,CAAC,yBAAyB,EAAE,IAAI,CAAC,CAAC;IAChD,WAAW,CAAC;QACV,MAAM,EAAE,yBAAyB;QACjC,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,UAAU,EAAE;YACV,EAAE,OAAO,EAAE,8BAA8B,OAAO,EAAE,EAAE,WAAW,EAAE,8BAA8B,EAAE;YACjG,EAAE,OAAO,EAAE,8BAA8B,EAAE,WAAW,EAAE,mCAAmC,EAAE;SAC9F;QACD,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,OAAO,uBAAuB,CAAC,CAAC,CAAC,WAAW,OAAO,yBAAyB,CAAC;KAC9G,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,eAAe;KACZ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,gDAAgD,CAAC;KAC7D,MAAM,CAAC,cAAc,EAAE,0CAA0C,CAAC;KAClE,MAAM,CAAC,aAAa,EAAE,4CAA4C,CAAC;KACnE,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAI,EAAE,EAAE;IACtC,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,IAAI,IAAI,CAAC,MAAM;QAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,IAAI,CAAC,KAAK;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,oBAAoB,kBAAkB,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACnH,cAAc,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAwB,CAAC;IAC3C,WAAW,CAAC;QACV,MAAM,EAAE,oBAAoB;QAC5B,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,UAAU,EAAE;YACV,EAAE,OAAO,EAAE,8BAA8B,OAAO,SAAS,EAAE,WAAW,EAAE,2BAA2B,EAAE;SACtG;QACD,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,yBAAyB,OAAO,EAAE,CAAC;KACtE,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,eAAe;KACZ,OAAO,CAAC,0BAA0B,CAAC;KACnC,WAAW,CAAC,oDAAoD,CAAC;KACjE,MAAM,CAAC,eAAe,EAAE,+BAA+B,EAAE,IAAI,CAAC;KAC9D,MAAM,CAAC,6BAA6B,EAAE,yCAAyC,CAAC;KAChF,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAY,EAAE,IAAI,EAAE,EAAE;IACpD,IAAI,IAAI,GAA4B,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,sBAAsB;YAC9B,KAAK,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,8BAA8B,GAAG,CAAC,OAAO,EAAE,EAAE;YACtF,cAAc,EAAE;gBACd,EAAE,OAAO,EAAE,8BAA8B,OAAO,IAAI,IAAI,2BAA2B,EAAE,WAAW,EAAE,uBAAuB,EAAE;aAC5H;SACF,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,IAAI,GAA4B,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAChE,IAAI,IAAI,CAAC,kBAAkB;QAAE,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,kBAAkB,CAAC;IACjF,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,oBAAoB,kBAAkB,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACvG,cAAc,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,IAA+F,CAAC;IAClH,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACnG,WAAW,CAAC;QACV,MAAM,EAAE,sBAAsB;QAC9B,MAAM,EAAE,IAAI,CAAC,IAAI;QACjB,UAAU,EAAE,IAAI,CAAC,UAAU;YACzB,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,4BAA4B,OAAO,EAAE,EAAE,WAAW,EAAE,wBAAwB,EAAE,CAAC;YAC7F,CAAC,CAAC;gBACE,EAAE,OAAO,EAAE,8BAA8B,EAAE,WAAW,EAAE,kCAAkC,EAAE;gBAC5F,EAAE,OAAO,EAAE,8BAA8B,OAAO,EAAE,EAAE,WAAW,EAAE,8BAA8B,EAAE;aAClG;QACL,KAAK,EAAE,IAAI,CAAC,UAAU;YACpB,CAAC,CAAC,CAAC,YAAY,IAAI,qCAAqC,OAAO,GAAG,CAAC;YACnE,CAAC,CAAC,CAAC,2BAA2B,IAAI,CAAC,KAAK,IAAI,SAAS,EAAE,CAAC;KAC3D,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usenaive-sdk/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for Naive AI Business Primitives API",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,10 +10,14 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"dist"
|
|
12
12
|
],
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
13
16
|
"scripts": {
|
|
14
17
|
"dev": "tsx src/index.ts",
|
|
15
18
|
"build": "tsc",
|
|
16
|
-
"typecheck": "tsc --noEmit"
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"prepublishOnly": "tsc"
|
|
17
21
|
},
|
|
18
22
|
"dependencies": {
|
|
19
23
|
"commander": "^13.1.0",
|