@dench.com/cli 3.8.6-staging.409 → 3.9.0-staging.417
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/app-sdk.d.ts +788 -26
- package/campaign.ts +94 -27
- package/crm.ts +157 -41
- package/dench.ts +4 -0
- package/lib/api-schemas.ts +126 -16
- package/lib/app-sdk-catalog.generated.ts +5 -5
- package/lib/campaign-agent.ts +26 -14
- package/lib/campaign-reference.ts +39 -0
- package/lib/command-registry.ts +10 -6
- package/lib/references.generated.json +14 -14
- package/lib/workspace-references.ts +205 -0
- package/package.json +1 -1
package/lib/api-schemas.ts
CHANGED
|
@@ -1346,6 +1346,59 @@ const crmFieldDoc = z
|
|
|
1346
1346
|
.passthrough()
|
|
1347
1347
|
.describe("A CRM field (column) document.");
|
|
1348
1348
|
|
|
1349
|
+
// Presentation metadata is separate from CRM field maps and optional on raw results.
|
|
1350
|
+
const referenceIdentity = {
|
|
1351
|
+
label: z.string(),
|
|
1352
|
+
href: z.string(),
|
|
1353
|
+
url: z.string().optional(),
|
|
1354
|
+
imageUrl: z.string().optional(),
|
|
1355
|
+
objectIcon: z.string().optional(),
|
|
1356
|
+
};
|
|
1357
|
+
const workspaceReference = z.discriminatedUnion("kind", [
|
|
1358
|
+
z.object({
|
|
1359
|
+
kind: z.literal("crm-entry"),
|
|
1360
|
+
objectName: z.string(),
|
|
1361
|
+
entryId: z.string(),
|
|
1362
|
+
...referenceIdentity,
|
|
1363
|
+
}),
|
|
1364
|
+
z.object({
|
|
1365
|
+
kind: z.literal("crm-object"),
|
|
1366
|
+
objectName: z.string(),
|
|
1367
|
+
...referenceIdentity,
|
|
1368
|
+
}),
|
|
1369
|
+
z.object({
|
|
1370
|
+
kind: z.literal("campaign"),
|
|
1371
|
+
sequenceId: z.string(),
|
|
1372
|
+
...referenceIdentity,
|
|
1373
|
+
}),
|
|
1374
|
+
]);
|
|
1375
|
+
const workspaceReferenceFields = {
|
|
1376
|
+
references: z.array(workspaceReference).max(100),
|
|
1377
|
+
referenceCoverage: z.object({
|
|
1378
|
+
returned: z.number().int().nonnegative(),
|
|
1379
|
+
available: z.number().int().nonnegative(),
|
|
1380
|
+
truncated: z.boolean(),
|
|
1381
|
+
}),
|
|
1382
|
+
};
|
|
1383
|
+
const optionalWorkspaceReferenceFields = {
|
|
1384
|
+
references: workspaceReferenceFields.references.optional(),
|
|
1385
|
+
referenceCoverage: workspaceReferenceFields.referenceCoverage.optional(),
|
|
1386
|
+
};
|
|
1387
|
+
const withReferencesRequest = {
|
|
1388
|
+
withReferences: z
|
|
1389
|
+
.boolean()
|
|
1390
|
+
.optional()
|
|
1391
|
+
.describe(
|
|
1392
|
+
"Include bounded navigation references. Array reads return {data, references, referenceCoverage}; existing result envelopes keep their fields.",
|
|
1393
|
+
),
|
|
1394
|
+
};
|
|
1395
|
+
function referenceListResponse<T extends z.ZodTypeAny>(row: T) {
|
|
1396
|
+
return z.union([
|
|
1397
|
+
z.array(row),
|
|
1398
|
+
z.object({ data: z.array(row), ...workspaceReferenceFields }),
|
|
1399
|
+
]);
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1349
1402
|
const crmEntryShape = z
|
|
1350
1403
|
.object({
|
|
1351
1404
|
id: z.string(),
|
|
@@ -1358,7 +1411,10 @@ const crmEntryShape = z
|
|
|
1358
1411
|
})
|
|
1359
1412
|
.describe("A materialized CRM entry (row).");
|
|
1360
1413
|
|
|
1361
|
-
const entryWriteResponse = z.object({
|
|
1414
|
+
const entryWriteResponse = z.object({
|
|
1415
|
+
entryId: z.string(),
|
|
1416
|
+
...optionalWorkspaceReferenceFields,
|
|
1417
|
+
});
|
|
1362
1418
|
|
|
1363
1419
|
const commentActorShape = z
|
|
1364
1420
|
.object({
|
|
@@ -1494,6 +1550,7 @@ const notificationPreferencesShape = z.object({
|
|
|
1494
1550
|
});
|
|
1495
1551
|
|
|
1496
1552
|
const crmBatchResults = z.object({
|
|
1553
|
+
...optionalWorkspaceReferenceFields,
|
|
1497
1554
|
results: z.array(
|
|
1498
1555
|
z
|
|
1499
1556
|
.object({
|
|
@@ -3283,6 +3340,7 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
|
|
|
3283
3340
|
"campaigns.accounts.linkedin": noInput,
|
|
3284
3341
|
"campaigns.accounts.email": noInput,
|
|
3285
3342
|
"campaigns.list": z.object({
|
|
3343
|
+
...withReferencesRequest,
|
|
3286
3344
|
includeArchived: z
|
|
3287
3345
|
.boolean()
|
|
3288
3346
|
.optional()
|
|
@@ -3882,7 +3940,7 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
|
|
|
3882
3940
|
"chat.follow": z.object({ threadId: z.string() }),
|
|
3883
3941
|
|
|
3884
3942
|
// CRM objects
|
|
3885
|
-
"crm.objects.list":
|
|
3943
|
+
"crm.objects.list": z.object(withReferencesRequest),
|
|
3886
3944
|
"crm.objects.listCompact": noInput,
|
|
3887
3945
|
"crm.objects.get": z.object({ name: z.string() }),
|
|
3888
3946
|
"crm.objects.create": z.object({
|
|
@@ -4086,6 +4144,7 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
|
|
|
4086
4144
|
|
|
4087
4145
|
// CRM entries
|
|
4088
4146
|
"crm.entries.list": z.object({
|
|
4147
|
+
...withReferencesRequest,
|
|
4089
4148
|
objectName: z.string(),
|
|
4090
4149
|
limit: z.coerce.number().int().min(1).max(1000).optional(),
|
|
4091
4150
|
...assigneeScopeRequest,
|
|
@@ -4473,6 +4532,7 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
|
|
|
4473
4532
|
|
|
4474
4533
|
// CRM query
|
|
4475
4534
|
"crm.query": z.object({
|
|
4535
|
+
...withReferencesRequest,
|
|
4476
4536
|
objectName: z.string(),
|
|
4477
4537
|
dsl: z
|
|
4478
4538
|
.object({
|
|
@@ -4497,6 +4557,17 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
|
|
|
4497
4557
|
),
|
|
4498
4558
|
...assigneeScopeRequest,
|
|
4499
4559
|
}),
|
|
4560
|
+
"crm.queryPage": z.object({
|
|
4561
|
+
objectName: z.string(),
|
|
4562
|
+
dsl: z.record(z.string(), z.unknown()).optional(),
|
|
4563
|
+
dslJson: z.string().optional(),
|
|
4564
|
+
...assigneeScopeRequest,
|
|
4565
|
+
...withReferencesRequest,
|
|
4566
|
+
paginationOpts: z.object({
|
|
4567
|
+
numItems: z.number().int().min(1).max(100),
|
|
4568
|
+
cursor: z.string().nullable(),
|
|
4569
|
+
}),
|
|
4570
|
+
}),
|
|
4500
4571
|
"crm.sql": z.object({
|
|
4501
4572
|
objectName: z.string(),
|
|
4502
4573
|
dsl: z.record(z.string(), z.unknown()).optional(),
|
|
@@ -4513,6 +4584,7 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
|
|
|
4513
4584
|
),
|
|
4514
4585
|
}),
|
|
4515
4586
|
"crm.search.page": z.object({
|
|
4587
|
+
...withReferencesRequest,
|
|
4516
4588
|
text: z.string().describe("Full-text query over readable entries."),
|
|
4517
4589
|
objectName: z.string().optional(),
|
|
4518
4590
|
select: z.array(z.string().min(1)).min(1).max(30).optional(),
|
|
@@ -4525,6 +4597,7 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
|
|
|
4525
4597
|
),
|
|
4526
4598
|
}),
|
|
4527
4599
|
"crm.search": z.object({
|
|
4600
|
+
...withReferencesRequest,
|
|
4528
4601
|
text: z.string().describe("Full-text query."),
|
|
4529
4602
|
objectName: z.string().optional().describe("Omit to search org-wide."),
|
|
4530
4603
|
limit: z.coerce.number().int().min(1).max(100).optional(),
|
|
@@ -4546,6 +4619,7 @@ export const requestSchemas: Record<string, ZodTypeAny> = {
|
|
|
4546
4619
|
|
|
4547
4620
|
// CRM batch + transactions
|
|
4548
4621
|
"crm.batch": z.object({
|
|
4622
|
+
...withReferencesRequest,
|
|
4549
4623
|
ops: z.array(crmOp).max(200),
|
|
4550
4624
|
idempotencyKey: z.string().optional(),
|
|
4551
4625
|
}),
|
|
@@ -5260,7 +5334,10 @@ export const responseSchemas: Record<string, ZodTypeAny> = {
|
|
|
5260
5334
|
previewRows: z.array(z.unknown()),
|
|
5261
5335
|
title: z.string(),
|
|
5262
5336
|
}),
|
|
5263
|
-
"campaigns.drafts.create": z.object({
|
|
5337
|
+
"campaigns.drafts.create": z.object({
|
|
5338
|
+
sequenceId: z.string(),
|
|
5339
|
+
...optionalWorkspaceReferenceFields,
|
|
5340
|
+
}),
|
|
5264
5341
|
"campaigns.audience.search": campaignSearchPage,
|
|
5265
5342
|
"campaigns.people.addBatch": campaignBatchResult,
|
|
5266
5343
|
"campaigns.people.addFromSearch": campaignSearchPage
|
|
@@ -5321,15 +5398,20 @@ export const responseSchemas: Record<string, ZodTypeAny> = {
|
|
|
5321
5398
|
// Outreach campaigns (dench campaign)
|
|
5322
5399
|
"campaigns.accounts.linkedin": z.array(campaignLinkedinSenderSummary),
|
|
5323
5400
|
"campaigns.accounts.email": z.array(campaignMailboxSummary),
|
|
5324
|
-
"campaigns.list":
|
|
5325
|
-
"campaigns.create": z.object({
|
|
5401
|
+
"campaigns.list": referenceListResponse(campaignRow),
|
|
5402
|
+
"campaigns.create": z.object({
|
|
5403
|
+
sequenceId: z.string(),
|
|
5404
|
+
...optionalWorkspaceReferenceFields,
|
|
5405
|
+
}),
|
|
5326
5406
|
"campaigns.duplicate": z.object({
|
|
5407
|
+
...optionalWorkspaceReferenceFields,
|
|
5327
5408
|
sequenceId: z
|
|
5328
5409
|
.string()
|
|
5329
5410
|
.describe("The new draft. Rename it with campaigns.update."),
|
|
5330
5411
|
}),
|
|
5331
5412
|
"campaigns.get": z
|
|
5332
5413
|
.object({
|
|
5414
|
+
...optionalWorkspaceReferenceFields,
|
|
5333
5415
|
sequence: campaignRow,
|
|
5334
5416
|
steps: z
|
|
5335
5417
|
.array(campaignStepInput.passthrough())
|
|
@@ -5719,7 +5801,7 @@ export const responseSchemas: Record<string, ZodTypeAny> = {
|
|
|
5719
5801
|
),
|
|
5720
5802
|
|
|
5721
5803
|
// CRM objects
|
|
5722
|
-
"crm.objects.list":
|
|
5804
|
+
"crm.objects.list": referenceListResponse(crmObjectDoc),
|
|
5723
5805
|
"crm.objects.listCompact": z.array(
|
|
5724
5806
|
z.object({
|
|
5725
5807
|
_id: z.string(),
|
|
@@ -5732,8 +5814,13 @@ export const responseSchemas: Record<string, ZodTypeAny> = {
|
|
|
5732
5814
|
archived: z.boolean(),
|
|
5733
5815
|
}),
|
|
5734
5816
|
),
|
|
5735
|
-
"crm.objects.get": crmObjectDoc
|
|
5736
|
-
|
|
5817
|
+
"crm.objects.get": crmObjectDoc
|
|
5818
|
+
.extend(optionalWorkspaceReferenceFields)
|
|
5819
|
+
.nullable(),
|
|
5820
|
+
"crm.objects.create": z.object({
|
|
5821
|
+
id: z.string(),
|
|
5822
|
+
...optionalWorkspaceReferenceFields,
|
|
5823
|
+
}),
|
|
5737
5824
|
"crm.objects.update": okResponse,
|
|
5738
5825
|
"crm.objects.rename": okResponse,
|
|
5739
5826
|
"crm.objects.delete": okResponse,
|
|
@@ -5833,7 +5920,7 @@ export const responseSchemas: Record<string, ZodTypeAny> = {
|
|
|
5833
5920
|
}),
|
|
5834
5921
|
|
|
5835
5922
|
// CRM entries + cells
|
|
5836
|
-
"crm.entries.list":
|
|
5923
|
+
"crm.entries.list": referenceListResponse(crmEntryShape),
|
|
5837
5924
|
"crm.views.entries": z
|
|
5838
5925
|
.object({
|
|
5839
5926
|
entries: z
|
|
@@ -5855,9 +5942,12 @@ export const responseSchemas: Record<string, ZodTypeAny> = {
|
|
|
5855
5942
|
.describe(
|
|
5856
5943
|
"The same payload the workspace table renders from (fields, statuses, savedViews, …).",
|
|
5857
5944
|
),
|
|
5858
|
-
"crm.entries.get": crmEntryShape
|
|
5945
|
+
"crm.entries.get": crmEntryShape
|
|
5946
|
+
.extend(optionalWorkspaceReferenceFields)
|
|
5947
|
+
.nullable(),
|
|
5859
5948
|
"crm.entries.create": entryWriteResponse,
|
|
5860
5949
|
"crm.entries.createMany": z.object({
|
|
5950
|
+
...optionalWorkspaceReferenceFields,
|
|
5861
5951
|
results: z.array(z.object({ entryId: z.string() })),
|
|
5862
5952
|
count: z.number(),
|
|
5863
5953
|
}),
|
|
@@ -5939,11 +6029,11 @@ export const responseSchemas: Record<string, ZodTypeAny> = {
|
|
|
5939
6029
|
"settings.sync.update": syncSettingsShape,
|
|
5940
6030
|
|
|
5941
6031
|
// CRM query + search
|
|
5942
|
-
"crm.query":
|
|
5943
|
-
.
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
6032
|
+
"crm.query": referenceListResponse(
|
|
6033
|
+
z.record(z.string(), z.unknown()),
|
|
6034
|
+
).describe(
|
|
6035
|
+
"Entry rows. With dsl.select the rows are flat {_id, ...selectedFields} objects instead.",
|
|
6036
|
+
),
|
|
5947
6037
|
"crm.sql": z
|
|
5948
6038
|
.array(crmEntryShape)
|
|
5949
6039
|
.describe(
|
|
@@ -5957,6 +6047,7 @@ export const responseSchemas: Record<string, ZodTypeAny> = {
|
|
|
5957
6047
|
}),
|
|
5958
6048
|
),
|
|
5959
6049
|
"crm.search.page": z.object({
|
|
6050
|
+
...optionalWorkspaceReferenceFields,
|
|
5960
6051
|
page: z.array(
|
|
5961
6052
|
z.object({ _id: z.string(), objectId: z.string(), data: fieldsMap }),
|
|
5962
6053
|
),
|
|
@@ -5966,7 +6057,7 @@ export const responseSchemas: Record<string, ZodTypeAny> = {
|
|
|
5966
6057
|
selectedFields: z.array(z.string()).nullable(),
|
|
5967
6058
|
completeness: z.literal("page"),
|
|
5968
6059
|
}),
|
|
5969
|
-
"crm.search":
|
|
6060
|
+
"crm.search": referenceListResponse(
|
|
5970
6061
|
z
|
|
5971
6062
|
.object({
|
|
5972
6063
|
_id: z.string(),
|
|
@@ -6551,11 +6642,30 @@ export const responseSchemas: Record<string, ZodTypeAny> = {
|
|
|
6551
6642
|
// ---------------------------------------------------------------------------
|
|
6552
6643
|
|
|
6553
6644
|
export type ConvexExtras = {
|
|
6645
|
+
withReferencesFunctionName?: string;
|
|
6554
6646
|
fixedArgs?: Record<string, unknown>;
|
|
6555
6647
|
transformArgs?: (input: Record<string, unknown>) => Record<string, unknown>;
|
|
6556
6648
|
};
|
|
6557
6649
|
|
|
6558
6650
|
export const convexExtras: Record<string, ConvexExtras> = {
|
|
6651
|
+
"campaigns.list": {
|
|
6652
|
+
withReferencesFunctionName:
|
|
6653
|
+
"functions/outreachSequences:listSequencesWithReferences",
|
|
6654
|
+
},
|
|
6655
|
+
"crm.objects.list": {
|
|
6656
|
+
withReferencesFunctionName: "functions/crm/objects:listWithReferences",
|
|
6657
|
+
},
|
|
6658
|
+
"crm.entries.list": {
|
|
6659
|
+
withReferencesFunctionName: "functions/crm/entries:listWithReferences",
|
|
6660
|
+
},
|
|
6661
|
+
"crm.query": {
|
|
6662
|
+
withReferencesFunctionName:
|
|
6663
|
+
"functions/crm/query:runQueryEntriesWithReferences",
|
|
6664
|
+
},
|
|
6665
|
+
"crm.search": {
|
|
6666
|
+
withReferencesFunctionName: "functions/crm/query:searchWithReferences",
|
|
6667
|
+
},
|
|
6668
|
+
|
|
6559
6669
|
"campaigns.steps.replace": {
|
|
6560
6670
|
transformArgs: ({ allowSingleBraces: _allowSingleBraces, ...input }) =>
|
|
6561
6671
|
input,
|
|
@@ -164,7 +164,7 @@ export const APP_SDK_OPERATIONS: readonly AppSdkOperationInfo[] = [
|
|
|
164
164
|
{"id":"chat.new","group":"chat","summary":"Start a new chat-turn workflow.","cli":"dench chat new","method":"POST","path":"/chat/threads","permission":"ai:chat","pathParams":[]},
|
|
165
165
|
{"id":"chat.send","group":"chat","summary":"Send a message to an existing chat thread.","cli":"dench chat send","method":"POST","path":"/chat/threads/{threadId}/messages","permission":"ai:chat","pathParams":["threadId"]},
|
|
166
166
|
{"id":"chat.follow","group":"chat","summary":"Follow a live chat response stream.","cli":"dench chat follow","method":"GET","path":"/chat/threads/{threadId}/stream","permission":"ai:chat","pathParams":["threadId"]},
|
|
167
|
-
{"id":"crm.objects.list","group":"crm","summary":"List CRM objects.","cli":"dench crm objects list","method":"GET","path":"/crm/objects","permission":"crm:read","pathParams":[]},
|
|
167
|
+
{"id":"crm.objects.list","group":"crm","summary":"List CRM objects.","cli":"dench crm objects list [--with-references]","method":"GET","path":"/crm/objects","permission":"crm:read","pathParams":[]},
|
|
168
168
|
{"id":"crm.objects.listCompact","group":"crm","summary":"List names, display labels, visibility and workspace counts without internal state.","cli":"dench crm objects list --compact","method":"GET","path":"/crm/catalog/objects","permission":"crm:read","pathParams":[]},
|
|
169
169
|
{"id":"crm.objects.get","group":"crm","summary":"Get a CRM object.","cli":"dench crm objects get","method":"GET","path":"/crm/objects/{name}","permission":"crm:read","pathParams":["name"]},
|
|
170
170
|
{"id":"crm.objects.create","group":"crm","summary":"Create a CRM object.","cli":"dench crm objects create","method":"POST","path":"/crm/objects","permission":"crm:write","pathParams":[]},
|
|
@@ -200,7 +200,7 @@ export const APP_SDK_OPERATIONS: readonly AppSdkOperationInfo[] = [
|
|
|
200
200
|
{"id":"crm.fields.enum.remove","group":"crm","summary":"Remove an enum value.","cli":"dench crm fields enum-remove","method":"DELETE","path":"/crm/objects/{objectName}/fields/{fieldName}/enum/{value}","permission":"crm:write","pathParams":["objectName","fieldName","value"]},
|
|
201
201
|
{"id":"crm.fields.enum.rename","group":"crm","summary":"Rename an enum value.","cli":"dench crm fields enum-rename","method":"POST","path":"/crm/objects/{objectName}/fields/{fieldName}/enum/{oldValue}/rename","permission":"crm:write","pathParams":["objectName","fieldName","oldValue"]},
|
|
202
202
|
{"id":"crm.fields.enum.color","group":"crm","summary":"Set an enum color.","cli":"dench crm fields enum-set-color","method":"POST","path":"/crm/objects/{objectName}/fields/{fieldName}/enum/{value}/color","permission":"crm:write","pathParams":["objectName","fieldName","value"]},
|
|
203
|
-
{"id":"crm.entries.list","group":"crm","summary":"List CRM entries.","cli":"dench crm entries list","method":"GET","path":"/crm/objects/{objectName}/entries","permission":"crm:read","pathParams":["objectName"]},
|
|
203
|
+
{"id":"crm.entries.list","group":"crm","summary":"List CRM entries.","cli":"dench crm entries list [--with-references]","method":"GET","path":"/crm/objects/{objectName}/entries","permission":"crm:read","pathParams":["objectName"]},
|
|
204
204
|
{"id":"crm.entries.get","group":"crm","summary":"Get a CRM entry.","cli":"dench crm entries get","method":"GET","path":"/crm/objects/{objectName}/entries/{entryId}","permission":"crm:read","pathParams":["objectName","entryId"]},
|
|
205
205
|
{"id":"crm.entries.syncHistory","group":"crm","summary":"Queue a full, paged pull of the record's email history from every connected mailbox; the ledger fills as pages land.","cli":"dench crm entries sync-history","method":"POST","path":"/crm/objects/{objectName}/entries/{entryId}/sync-history","permission":"crm:write","pathParams":["objectName","entryId"]},
|
|
206
206
|
{"id":"crm.entries.syncHistoryStatus","group":"crm","summary":"Has Dench read this record's email history? One row per address per mailbox.","cli":"dench crm entries sync-history --status","method":"GET","path":"/crm/objects/{objectName}/entries/{entryId}/sync-history","permission":"crm:read","pathParams":["objectName","entryId"]},
|
|
@@ -258,11 +258,11 @@ export const APP_SDK_OPERATIONS: readonly AppSdkOperationInfo[] = [
|
|
|
258
258
|
{"id":"crm.cells.set","group":"crm","summary":"Set a CRM cell value.","cli":"dench crm cells set","method":"PUT","path":"/crm/objects/{objectName}/entries/{entryId}/fields/{fieldName}","permission":"crm:write","pathParams":["objectName","entryId","fieldName"]},
|
|
259
259
|
{"id":"crm.cells.setMany","group":"crm","summary":"Set many CRM cell values.","cli":"dench crm cells set-many","method":"POST","path":"/crm/cells/batch","permission":"crm:write","pathParams":[]},
|
|
260
260
|
{"id":"crm.cells.append","group":"crm","summary":"Append to a CRM cell.","cli":"dench crm cells append","method":"POST","path":"/crm/objects/{objectName}/entries/{entryId}/fields/{fieldName}/append","permission":"crm:write","pathParams":["objectName","entryId","fieldName"]},
|
|
261
|
-
{"id":"crm.query","group":"crm","summary":"Query CRM entries.","cli":"dench crm query","method":"POST","path":"/crm/query","permission":"crm:read","pathParams":[]},
|
|
261
|
+
{"id":"crm.query","group":"crm","summary":"Query CRM entries.","cli":"dench crm query [--with-references]","method":"POST","path":"/crm/query","permission":"crm:read","pathParams":[]},
|
|
262
262
|
{"id":"crm.queryPage","group":"crm","summary":"Scan CRM entries with a resumable cursor. Empty filtered pages can have more results.","cli":"dench crm query --page","method":"POST","path":"/crm/query/page","permission":"crm:read","pathParams":[]},
|
|
263
263
|
{"id":"crm.sql","group":"crm","summary":"Run CRM SQL-compatible query.","cli":"dench crm sql","method":"POST","path":"/crm/sql","permission":"crm:read","pathParams":[]},
|
|
264
264
|
{"id":"crm.aggregate","group":"crm","summary":"Aggregate CRM entries.","cli":"dench crm aggregate","method":"POST","path":"/crm/aggregate","permission":"crm:read","pathParams":[]},
|
|
265
|
-
{"id":"crm.search","group":"crm","summary":"Search CRM entries.","cli":"dench crm search","method":"GET","path":"/crm/search","permission":"crm:read","pathParams":[]},
|
|
265
|
+
{"id":"crm.search","group":"crm","summary":"Search CRM entries.","cli":"dench crm search [--with-references]","method":"GET","path":"/crm/search","permission":"crm:read","pathParams":[]},
|
|
266
266
|
{"id":"crm.search.page","group":"crm","summary":"Search bounded pages of readable CRM entries, optionally projecting cells. Always follow continueCursor until isDone.","cli":"dench crm search --page","method":"GET","path":"/crm/search/page","permission":"crm:read","pathParams":[]},
|
|
267
267
|
{"id":"crm.statuses.list","group":"crm","summary":"List CRM statuses.","cli":"dench crm statuses list","method":"GET","path":"/crm/objects/{objectName}/statuses","permission":"crm:read","pathParams":["objectName"]},
|
|
268
268
|
{"id":"crm.statuses.set","group":"crm","summary":"Set CRM statuses.","cli":"dench crm statuses set","method":"PUT","path":"/crm/objects/{objectName}/statuses","permission":"crm:write","pathParams":["objectName"]},
|
|
@@ -388,7 +388,7 @@ export const APP_SDK_OPERATIONS: readonly AppSdkOperationInfo[] = [
|
|
|
388
388
|
{"id":"email.sequence.enrollment.stop","group":"email","summary":"Stop one enrollment (no further steps send).","cli":"dench email sequence enrollment stop","method":"POST","path":"/email/sequences/enrollments/{enrollmentId}/stop","permission":"email:write","pathParams":["enrollmentId"]},
|
|
389
389
|
{"id":"campaigns.accounts.linkedin","group":"campaigns","summary":"Discover LinkedIn sender ids, labels, availability and remaining capacity visible to the acting workspace member. Never returns provider credentials.","cli":"dench campaign accounts","method":"GET","path":"/campaigns/accounts/linkedin","permission":"campaigns:read","pathParams":[]},
|
|
390
390
|
{"id":"campaigns.accounts.email","group":"campaigns","summary":"Discover the mailboxes the acting workspace member can send campaign email from: ids for emailMailboxAccountIds, status, warm-up state and when it is done, the daily cold-email cap and what is left today. Never returns provider credentials.","cli":"dench campaign accounts","method":"GET","path":"/campaigns/accounts/email","permission":"campaigns:read","pathParams":[]},
|
|
391
|
-
{"id":"campaigns.list","group":"campaigns","summary":"List outreach campaigns (archived ones on request).","cli":"dench campaign list","method":"GET","path":"/campaigns","permission":"campaigns:read","pathParams":[]},
|
|
391
|
+
{"id":"campaigns.list","group":"campaigns","summary":"List outreach campaigns (archived ones on request).","cli":"dench campaign list [--with-references]","method":"GET","path":"/campaigns","permission":"campaigns:read","pathParams":[]},
|
|
392
392
|
{"id":"campaigns.create","group":"campaigns","summary":"Create a draft outreach campaign with email and LinkedIn sender pools and a business-hours send window in the given timezone.","cli":"dench campaign create","method":"POST","path":"/campaigns","permission":"campaigns:write","pathParams":[]},
|
|
393
393
|
{"id":"campaigns.duplicate","group":"campaigns","summary":"Copy a campaign into a new draft named \"<name> copy\": the same steps, schedule, sender pools and personalized lines, its lead source paused, and no people. To reach more than 300 people, duplicate and add the next page of the search to the copy.","cli":"dench campaign duplicate","method":"POST","path":"/campaigns/{sequenceId}/duplicate","permission":"campaigns:write","pathParams":["sequenceId"]},
|
|
394
394
|
{"id":"campaigns.get","group":"campaigns","summary":"Read a campaign: settings, steps, people, their current step and hold, last touches, linked leads.","cli":"dench campaign get","method":"GET","path":"/campaigns/{sequenceId}","permission":"campaigns:read","pathParams":["sequenceId"]},
|
package/lib/campaign-agent.ts
CHANGED
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
SEARCH_TEXT_FLAGS,
|
|
37
37
|
usesSearchFlags,
|
|
38
38
|
} from "./campaign-filters";
|
|
39
|
+
import { campaignReferenceResult } from "./campaign-reference";
|
|
39
40
|
import {
|
|
40
41
|
assertNoUnknownFlags,
|
|
41
42
|
getFlag,
|
|
@@ -59,6 +60,7 @@ type Context = {
|
|
|
59
60
|
jsonOutput: boolean;
|
|
60
61
|
sessionToken?: string;
|
|
61
62
|
host?: string;
|
|
63
|
+
workspaceSlug?: string;
|
|
62
64
|
resolveCampaign: (reference: string) => Promise<CampaignRef>;
|
|
63
65
|
};
|
|
64
66
|
|
|
@@ -1349,6 +1351,7 @@ async function addRecipients(
|
|
|
1349
1351
|
}
|
|
1350
1352
|
|
|
1351
1353
|
type CampaignSettings = {
|
|
1354
|
+
references?: unknown[];
|
|
1352
1355
|
_id: string;
|
|
1353
1356
|
name: string;
|
|
1354
1357
|
status: string;
|
|
@@ -1373,7 +1376,10 @@ async function readCampaign(
|
|
|
1373
1376
|
throw new Error(
|
|
1374
1377
|
`Campaign ${sequenceId} could not be read back. Run dench campaign list to find it.`,
|
|
1375
1378
|
);
|
|
1376
|
-
return
|
|
1379
|
+
return {
|
|
1380
|
+
...detail.sequence,
|
|
1381
|
+
references: (detail as { references?: unknown[] }).references,
|
|
1382
|
+
};
|
|
1377
1383
|
}
|
|
1378
1384
|
|
|
1379
1385
|
function plural(count: number, one: string, many: string) {
|
|
@@ -1442,20 +1448,26 @@ async function draft(ctx: Context) {
|
|
|
1442
1448
|
.join("; ");
|
|
1443
1449
|
return print(
|
|
1444
1450
|
ctx,
|
|
1445
|
-
|
|
1451
|
+
campaignReferenceResult(
|
|
1452
|
+
ctx,
|
|
1453
|
+
{
|
|
1454
|
+
references: campaign.references,
|
|
1455
|
+
sequenceId,
|
|
1456
|
+
name: campaign.name,
|
|
1457
|
+
status: campaign.status,
|
|
1458
|
+
clientRequestId,
|
|
1459
|
+
timezone: campaign.timezone ?? timezone,
|
|
1460
|
+
sendSchedules,
|
|
1461
|
+
dailySendCap: campaign.dailySendCap ?? null,
|
|
1462
|
+
stopOnReply: campaign.stopOnReply !== false,
|
|
1463
|
+
...(campaign.startsAt ? { startsAt: campaign.startsAt } : {}),
|
|
1464
|
+
...(campaign.endsAt ? { endsAt: campaign.endsAt } : {}),
|
|
1465
|
+
emailMailboxAccountIds,
|
|
1466
|
+
linkedinAccountIds,
|
|
1467
|
+
},
|
|
1446
1468
|
sequenceId,
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
clientRequestId,
|
|
1450
|
-
timezone: campaign.timezone ?? timezone,
|
|
1451
|
-
sendSchedules,
|
|
1452
|
-
dailySendCap: campaign.dailySendCap ?? null,
|
|
1453
|
-
stopOnReply: campaign.stopOnReply !== false,
|
|
1454
|
-
...(campaign.startsAt ? { startsAt: campaign.startsAt } : {}),
|
|
1455
|
-
...(campaign.endsAt ? { endsAt: campaign.endsAt } : {}),
|
|
1456
|
-
emailMailboxAccountIds,
|
|
1457
|
-
linkedinAccountIds,
|
|
1458
|
-
},
|
|
1469
|
+
campaign.name,
|
|
1470
|
+
),
|
|
1459
1471
|
`Draft "${campaign.name}" [${sequenceId}] · ${windows || "no send window"} · ${plural(emailMailboxAccountIds.length, "mailbox", "mailboxes")}, ${plural(linkedinAccountIds.length, "LinkedIn account", "LinkedIn accounts")} · request id ${clientRequestId}`,
|
|
1460
1472
|
);
|
|
1461
1473
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
boundWorkspaceReferences,
|
|
3
|
+
parseWorkspaceReference,
|
|
4
|
+
type WorkspaceReference,
|
|
5
|
+
withWorkspaceReferenceUrls,
|
|
6
|
+
workspaceReferenceHref,
|
|
7
|
+
} from "./workspace-references";
|
|
8
|
+
|
|
9
|
+
export function campaignReferenceResult(
|
|
10
|
+
context: { host?: string; workspaceSlug?: string },
|
|
11
|
+
result: Record<string, unknown>,
|
|
12
|
+
sequenceId: string,
|
|
13
|
+
label: string,
|
|
14
|
+
) {
|
|
15
|
+
const inherited = Array.isArray(result.references)
|
|
16
|
+
? result.references
|
|
17
|
+
.map(parseWorkspaceReference)
|
|
18
|
+
.find(
|
|
19
|
+
(ref) => ref?.kind === "campaign" && ref.sequenceId === sequenceId,
|
|
20
|
+
)
|
|
21
|
+
: undefined;
|
|
22
|
+
const identity = { kind: "campaign" as const, sequenceId };
|
|
23
|
+
const reference: WorkspaceReference = withWorkspaceReferenceUrls(
|
|
24
|
+
{
|
|
25
|
+
...identity,
|
|
26
|
+
label,
|
|
27
|
+
href: workspaceReferenceHref(identity),
|
|
28
|
+
...(inherited?.imageUrl ? { imageUrl: inherited.imageUrl } : {}),
|
|
29
|
+
...(inherited?.objectIcon ? { objectIcon: inherited.objectIcon } : {}),
|
|
30
|
+
},
|
|
31
|
+
context,
|
|
32
|
+
);
|
|
33
|
+
return {
|
|
34
|
+
...result,
|
|
35
|
+
...boundWorkspaceReferences([reference]),
|
|
36
|
+
href: reference.href,
|
|
37
|
+
...(reference.url ? { url: reference.url } : {}),
|
|
38
|
+
};
|
|
39
|
+
}
|
package/lib/command-registry.ts
CHANGED
|
@@ -7,6 +7,8 @@ export type ConvexOperation = {
|
|
|
7
7
|
kind: "convex";
|
|
8
8
|
functionType: "query" | "mutation" | "action";
|
|
9
9
|
functionName: string;
|
|
10
|
+
/** Explicit envelope variant; the legacy function keeps its array contract. */
|
|
11
|
+
withReferencesFunctionName?: string;
|
|
10
12
|
auth: ApiAuthMode;
|
|
11
13
|
tokenArg?: "sessionToken" | "apiKey";
|
|
12
14
|
includeRunId?: boolean;
|
|
@@ -1293,7 +1295,7 @@ const rawApiOperations = [
|
|
|
1293
1295
|
id: "crm.objects.list",
|
|
1294
1296
|
group: "crm",
|
|
1295
1297
|
summary: "List CRM objects.",
|
|
1296
|
-
cli: "dench crm objects list",
|
|
1298
|
+
cli: "dench crm objects list [--with-references]",
|
|
1297
1299
|
method: "GET",
|
|
1298
1300
|
path: "/crm/objects",
|
|
1299
1301
|
requestSchema: noBody,
|
|
@@ -1715,10 +1717,12 @@ const rawApiOperations = [
|
|
|
1715
1717
|
id: "crm.entries.list",
|
|
1716
1718
|
group: "crm",
|
|
1717
1719
|
summary: "List CRM entries.",
|
|
1718
|
-
cli: "dench crm entries list",
|
|
1720
|
+
cli: "dench crm entries list [--with-references]",
|
|
1719
1721
|
method: "GET",
|
|
1720
1722
|
path: "/crm/objects/{objectName}/entries",
|
|
1721
|
-
requestSchema:
|
|
1723
|
+
requestSchema: z
|
|
1724
|
+
.object({ withReferences: z.boolean().optional() })
|
|
1725
|
+
.passthrough(),
|
|
1722
1726
|
responseSchema: anyResponse,
|
|
1723
1727
|
backend: convex("query", "functions/crm/entries:list"),
|
|
1724
1728
|
}),
|
|
@@ -2604,7 +2608,7 @@ const rawApiOperations = [
|
|
|
2604
2608
|
id: "crm.query",
|
|
2605
2609
|
group: "crm",
|
|
2606
2610
|
summary: "Query CRM entries.",
|
|
2607
|
-
cli: "dench crm query",
|
|
2611
|
+
cli: "dench crm query [--with-references]",
|
|
2608
2612
|
method: "POST",
|
|
2609
2613
|
path: "/crm/query",
|
|
2610
2614
|
requestSchema: anyObject,
|
|
@@ -2649,7 +2653,7 @@ const rawApiOperations = [
|
|
|
2649
2653
|
id: "crm.search",
|
|
2650
2654
|
group: "crm",
|
|
2651
2655
|
summary: "Search CRM entries.",
|
|
2652
|
-
cli: "dench crm search",
|
|
2656
|
+
cli: "dench crm search [--with-references]",
|
|
2653
2657
|
method: "GET",
|
|
2654
2658
|
path: "/crm/search",
|
|
2655
2659
|
requestSchema: anyObject,
|
|
@@ -4275,7 +4279,7 @@ const rawApiOperations = [
|
|
|
4275
4279
|
id: "campaigns.list",
|
|
4276
4280
|
group: "campaigns",
|
|
4277
4281
|
summary: "List outreach campaigns (archived ones on request).",
|
|
4278
|
-
cli: "dench campaign list",
|
|
4282
|
+
cli: "dench campaign list [--with-references]",
|
|
4279
4283
|
method: "GET",
|
|
4280
4284
|
path: "/campaigns",
|
|
4281
4285
|
requestSchema: anyObject,
|