@startanaicompany/crm 2.6.0 → 2.8.0
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/index.js +62 -2
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -395,7 +395,7 @@ leadsCmd
|
|
|
395
395
|
.option('--phone <phone>', 'Phone number')
|
|
396
396
|
.option('--company <company>', 'Company name')
|
|
397
397
|
.option('--status <status>', 'Status: new|contacted|qualified|unresponsive|converted|lost', 'new')
|
|
398
|
-
.option('--source <source>', 'Source: api|import|referral', 'api')
|
|
398
|
+
.option('--source <source>', 'Source: api|import|referral|linkedin|cold_email|website|inbound|partner|event|other', 'api')
|
|
399
399
|
.option('--deal-value <amount>', 'Deal value (numeric)')
|
|
400
400
|
.option('--pipeline-stage <stage>', 'Pipeline stage: new|prospecting|discovery|qualified|demo_scheduled|demo_completed|proposal_sent|negotiation|contract_sent|closed_won|closed_lost|no_decision|dormant')
|
|
401
401
|
.option('--notes <notes>', 'Notes')
|
|
@@ -439,10 +439,15 @@ leadsCmd
|
|
|
439
439
|
.option('--email <email>', 'Filter by email (partial match)')
|
|
440
440
|
.option('--company <company>', 'Filter by company (partial match)')
|
|
441
441
|
.option('--name <name>', 'Search by name or company (partial match)')
|
|
442
|
+
.option('--assigned-to <assignedTo>', 'Filter by assigned-to (partial match)')
|
|
442
443
|
.option('--pipeline-stage <stage>', 'Filter by pipeline stage (exact match)')
|
|
443
444
|
.option('--tag <tag>', 'Filter by tag — repeatable, AND logic', (v, prev) => prev.concat([v]), [])
|
|
444
445
|
.option('--api-key-id <id>', 'Filter by the API key ID that created the lead')
|
|
445
446
|
.option('--self', 'Filter leads created by the current API key (shorthand for --api-key-id self)')
|
|
447
|
+
.option('--sort-by <field>', 'Sort field: created_at|updated_at|deal_value|name|company|last_activity_at|status_changed_at|score')
|
|
448
|
+
.option('--order <dir>', 'Sort direction: asc|desc', 'desc')
|
|
449
|
+
.option('--score-min <n>', 'Filter leads with score >= n (0-100)')
|
|
450
|
+
.option('--score-max <n>', 'Filter leads with score <= n (0-100)')
|
|
446
451
|
.option('--created-after <date>', 'Filter leads created after this ISO8601 date (e.g. 2026-01-01T00:00:00Z)')
|
|
447
452
|
.option('--created-before <date>', 'Filter leads created before this ISO8601 date')
|
|
448
453
|
.option('--updated-after <date>', 'Filter leads updated after this ISO8601 date')
|
|
@@ -459,8 +464,13 @@ leadsCmd
|
|
|
459
464
|
...(opts.email && { email: opts.email }),
|
|
460
465
|
...(opts.company && { company: opts.company }),
|
|
461
466
|
...(opts.name && { name: opts.name }),
|
|
467
|
+
...(opts.assignedTo && { assigned_to: opts.assignedTo }),
|
|
462
468
|
...(opts.pipelineStage && { pipeline_stage: opts.pipelineStage }),
|
|
463
469
|
...(apiKeyIdFilter && { api_key_id: apiKeyIdFilter }),
|
|
470
|
+
...(opts.sortBy && { sort_by: opts.sortBy }),
|
|
471
|
+
...(opts.order && { order: opts.order }),
|
|
472
|
+
...(opts.scoreMin !== undefined && { score_min: opts.scoreMin }),
|
|
473
|
+
...(opts.scoreMax !== undefined && { score_max: opts.scoreMax }),
|
|
464
474
|
...(opts.createdAfter && { created_after: opts.createdAfter }),
|
|
465
475
|
...(opts.createdBefore && { created_before: opts.createdBefore }),
|
|
466
476
|
...(opts.updatedAfter && { updated_after: opts.updatedAfter }),
|
|
@@ -479,9 +489,59 @@ leadsCmd
|
|
|
479
489
|
}
|
|
480
490
|
});
|
|
481
491
|
|
|
492
|
+
leadsCmd
|
|
493
|
+
.command('bulk-create')
|
|
494
|
+
.description('Bulk create up to 100 leads from a JSON file (207 Multi-Status)')
|
|
495
|
+
.requiredOption('--file <path>', 'Path to JSON file containing array of lead objects')
|
|
496
|
+
.option('--fail-fast', 'Stop processing on first failure', false)
|
|
497
|
+
.option('--from-agent-name <name>', 'Agent name for attribution (falls back to config defaultAgentName)')
|
|
498
|
+
.action(async (opts) => {
|
|
499
|
+
const globalOpts = program.opts();
|
|
500
|
+
const agentName = resolveAgentName(opts.fromAgentName);
|
|
501
|
+
const client = getClient(globalOpts, agentName);
|
|
502
|
+
let leads;
|
|
503
|
+
try {
|
|
504
|
+
const fs = require('fs');
|
|
505
|
+
const raw = fs.readFileSync(opts.file, 'utf8');
|
|
506
|
+
const parsed = JSON.parse(raw);
|
|
507
|
+
leads = Array.isArray(parsed) ? parsed : parsed.leads;
|
|
508
|
+
if (!Array.isArray(leads)) throw new Error('JSON must be an array or object with a "leads" array');
|
|
509
|
+
} catch (fileErr) {
|
|
510
|
+
console.error(`Error reading file: ${fileErr.message}`);
|
|
511
|
+
process.exit(1);
|
|
512
|
+
}
|
|
513
|
+
try {
|
|
514
|
+
const res = await client.post('/leads/bulk', { leads, fail_fast: opts.failFast });
|
|
515
|
+
printJSON(res.data);
|
|
516
|
+
} catch (err) {
|
|
517
|
+
handleError(err);
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
leadsCmd
|
|
522
|
+
.command('score')
|
|
523
|
+
.description('Set lead score (0-100). Conventions: 0-19 Cold, 20-39 Warm, 40-59 Developing, 60-79 Qualified, 80-100 Hot')
|
|
524
|
+
.requiredOption('--id <uuid>', 'Lead UUID')
|
|
525
|
+
.requiredOption('--score <n>', 'Score value (0-100 integer)')
|
|
526
|
+
.option('--reason <text>', 'Score reason/explanation')
|
|
527
|
+
.action(async (opts) => {
|
|
528
|
+
const globalOpts = program.opts();
|
|
529
|
+
const client = getClient(globalOpts);
|
|
530
|
+
const body = {
|
|
531
|
+
score: parseInt(opts.score),
|
|
532
|
+
...(opts.reason && { score_reason: opts.reason })
|
|
533
|
+
};
|
|
534
|
+
try {
|
|
535
|
+
const res = await client.patch(`/leads/${opts.id}/score`, body);
|
|
536
|
+
printJSON(res.data);
|
|
537
|
+
} catch (err) {
|
|
538
|
+
handleError(err);
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
|
|
482
542
|
leadsCmd
|
|
483
543
|
.command('get <id>')
|
|
484
|
-
.description('Get a single lead by ID')
|
|
544
|
+
.description('Get a single lead by ID (includes activity_summary)')
|
|
485
545
|
.action(async (id) => {
|
|
486
546
|
const globalOpts = program.opts();
|
|
487
547
|
const client = getClient(globalOpts);
|