@dench.com/cli 3.6.1-staging.362 → 3.6.3-staging.372

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 CHANGED
@@ -1040,6 +1040,8 @@ export interface ApiRequests {
1040
1040
  "crm.activity.list": Record<string, unknown>;
1041
1041
  /** The record's generated Brief: health, who owes the next move, open threads, commitments, risks, next step. Read this before the ledger. — `dench crm brief` — GET /api/v1/crm/objects/{objectName}/entries/{entryId}/brief */
1042
1042
  "crm.brief.get": Record<string, unknown>;
1043
+ /** Read-only source diagnostics: accessible evidence, association reasons, last Brief source manifest, generation queue, and your mailbox delivery health. Bounded, cursor-paged snapshot; does not certify complete history. — `dench crm context` — GET /api/v1/crm/objects/{objectName}/entries/{entryId}/context */
1044
+ "crm.context.get": Record<string, unknown>;
1043
1045
  /** Rebuild a record's Brief from the current timeline. — `dench crm brief --regenerate` — POST /api/v1/crm/objects/{objectName}/entries/{entryId}/brief/regenerate */
1044
1046
  "crm.brief.regenerate": Record<string, unknown>;
1045
1047
  /** Bounded per-source counts of a CRM entry's activity ledger. — `dench crm activity` — GET /api/v1/crm/objects/{objectName}/entries/{entryId}/activity/count */
@@ -4175,6 +4177,7 @@ export interface ApiResponses {
4175
4177
  "crm.entries.history": unknown;
4176
4178
  "crm.activity.list": unknown;
4177
4179
  "crm.brief.get": unknown;
4180
+ "crm.context.get": unknown;
4178
4181
  "crm.brief.regenerate": unknown;
4179
4182
  "crm.activity.count": unknown;
4180
4183
  "crm.notes.list": unknown;
@@ -7507,6 +7510,10 @@ export type DenchApiTree = {
7507
7510
  /** Search for companies through the enrichment gateway (also `dench companies find`). (`dench crm companies search`) */
7508
7511
  search(args: Req<"crm.companies.search">): Promise<Res<"crm.companies.search">>;
7509
7512
  };
7513
+ context: {
7514
+ /** Read-only source diagnostics: accessible evidence, association reasons, last Brief source manifest, generation queue, and your mailbox delivery health. Bounded, cursor-paged snapshot; does not certify complete history. (`dench crm context`) */
7515
+ get(args: Req<"crm.context.get">): Promise<Res<"crm.context.get">>;
7516
+ };
7510
7517
  detections: {
7511
7518
  /** List account-detection verdicts — why a domain (or personal address) did or did not become an account: verdict, counterparty type, probabilities, evidence threads, the rows created. `kind` picks the creator: `detections` (email + sweep), `linkedin` (the LinkedIn resolver's rows) or `all` (default). Newest first. (`dench crm detections list`) */
7512
7519
  list(args?: Req<"crm.detections.list">): Promise<Res<"crm.detections.list">>;
package/crm-context.ts ADDED
@@ -0,0 +1,66 @@
1
+ import { makeFunctionReference } from "convex/server";
2
+ import {
3
+ assertNoUnknownFlags,
4
+ type CrmCliContext,
5
+ callQuery,
6
+ out,
7
+ shift,
8
+ } from "./crm";
9
+ import { getFlag } from "./lib/cli-args";
10
+
11
+ const getContext = makeFunctionReference<"query">(
12
+ "functions/crm/contextDiagnostics:getForEntry",
13
+ );
14
+
15
+ // Keep the shipped CLI independent of application-only Convex source files.
16
+ type ContextPage = {
17
+ record: { label: string };
18
+ generation: { state: string };
19
+ scopeLimited: boolean;
20
+ sourceLimited: boolean;
21
+ sources: Array<{
22
+ occurredAt: number;
23
+ kind: string;
24
+ title: string;
25
+ association: string;
26
+ usedByLastBrief: boolean;
27
+ sourceTable: string;
28
+ sourceId: string;
29
+ }>;
30
+ mailboxes: Array<{ email: string; label: string }>;
31
+ nextCursor: string | null;
32
+ };
33
+
34
+ /** Read-only: inspecting a sync never starts a generation or connector call. */
35
+ export async function runContextCommand(ctx: CrmCliContext): Promise<void> {
36
+ const objectName = shift(ctx.args, "object name");
37
+ const entryId = shift(ctx.args, "entry id");
38
+ const cursor = getFlag(ctx.args, "--cursor");
39
+ assertNoUnknownFlags(ctx.args, "crm context");
40
+ const result = (await callQuery(ctx, getContext, {
41
+ objectName,
42
+ entryId,
43
+ ...(cursor ? { cursor } : {}),
44
+ })) as ContextPage;
45
+ if (ctx.jsonOutput) {
46
+ out(ctx, result);
47
+ return;
48
+ }
49
+ const lines = [
50
+ `${result.record.label} · Brief ${result.generation.state}`,
51
+ "Bounded snapshot of sources you can access; complete history is not certified.",
52
+ ...(result.scopeLimited ? ["Related-record scope reached its limit."] : []),
53
+ ...(result.sourceLimited
54
+ ? ["Source inspection reached its read limit."]
55
+ : []),
56
+ ...result.sources.map(
57
+ (row) =>
58
+ `${new Date(row.occurredAt).toISOString()} ${row.kind} ${row.title} [${row.association}; ${row.usedByLastBrief ? "used by last Brief" : "not in last Brief"}] ${row.sourceTable}:${row.sourceId}`,
59
+ ),
60
+ ...result.mailboxes.map((row) => `${row.email}: ${row.label}`),
61
+ ...(result.nextCursor
62
+ ? [`More sources: repeat with --cursor '${result.nextCursor}'`]
63
+ : []),
64
+ ];
65
+ out(ctx, lines.join("\n"));
66
+ }
package/crm.ts CHANGED
@@ -40,6 +40,7 @@ import {
40
40
  runTasksCommand,
41
41
  runWatchCommand,
42
42
  } from "./crm-comments";
43
+ import { runContextCommand } from "./crm-context";
43
44
  import { runDetectionsCommand } from "./crm-detections";
44
45
  import { runPrivacyCommand } from "./crm-privacy";
45
46
  import {
@@ -1087,6 +1088,8 @@ export async function runCrmCommand(opts: {
1087
1088
  return await runActivityCommand(ctx);
1088
1089
  case "brief":
1089
1090
  return await runBriefCommand(ctx);
1091
+ case "context":
1092
+ return await runContextCommand(ctx);
1090
1093
  case "notes":
1091
1094
  return await runNotesCommand(ctx);
1092
1095
  case "watch":
@@ -1164,6 +1167,7 @@ const CRM_SUBCOMMANDS = [
1164
1167
  "comments",
1165
1168
  "activity",
1166
1169
  "brief",
1170
+ "context",
1167
1171
  "notes",
1168
1172
  "watch",
1169
1173
  "tasks",
@@ -4775,6 +4779,7 @@ Privacy (sharing is the default; this is YOUR opt-out for one record):
4775
4779
 
4776
4780
  Brief (what the record means right now — the FIRST thing to read):
4777
4781
  dench crm brief <object> <entryId> [--regenerate] [--json]
4782
+ dench crm context <object> <entryId> [--cursor <cursor>] [--json]
4778
4783
  Generated from the timeline; read-only. Health, who owes the next
4779
4784
  move, open threads, commitments, risks, next step.
4780
4785
  Empty on a record nobody has opened yet — the call itself starts one;
@@ -186,6 +186,7 @@ export const APP_SDK_OPERATIONS: readonly AppSdkOperationInfo[] = [
186
186
  {"id":"crm.entries.history","group":"crm","summary":"List a CRM entry's audit history.","cli":"dench crm history","method":"GET","path":"/crm/objects/{objectName}/entries/{entryId}/history","permission":"crm:read","pathParams":["objectName","entryId"]},
187
187
  {"id":"crm.activity.list","group":"crm","summary":"List a CRM entry's activity ledger (comments, notes, field changes, emails, meetings, Slack, LinkedIn) in one timeline, newest first by default.","cli":"dench crm activity","method":"GET","path":"/crm/objects/{objectName}/entries/{entryId}/activity","permission":"crm:read","pathParams":["objectName","entryId"]},
188
188
  {"id":"crm.brief.get","group":"crm","summary":"The record's generated Brief: health, who owes the next move, open threads, commitments, risks, next step. Read this before the ledger.","cli":"dench crm brief","method":"GET","path":"/crm/objects/{objectName}/entries/{entryId}/brief","permission":"crm:read","pathParams":["objectName","entryId"]},
189
+ {"id":"crm.context.get","group":"crm","summary":"Read-only source diagnostics: accessible evidence, association reasons, last Brief source manifest, generation queue, and your mailbox delivery health. Bounded, cursor-paged snapshot; does not certify complete history.","cli":"dench crm context","method":"GET","path":"/crm/objects/{objectName}/entries/{entryId}/context","permission":"crm:read","pathParams":["objectName","entryId"]},
189
190
  {"id":"crm.brief.regenerate","group":"crm","summary":"Rebuild a record's Brief from the current timeline.","cli":"dench crm brief --regenerate","method":"POST","path":"/crm/objects/{objectName}/entries/{entryId}/brief/regenerate","permission":"crm:write","pathParams":["objectName","entryId"]},
190
191
  {"id":"crm.activity.count","group":"crm","summary":"Bounded per-source counts of a CRM entry's activity ledger.","cli":"dench crm activity","method":"GET","path":"/crm/objects/{objectName}/entries/{entryId}/activity/count","permission":"crm:read","pathParams":["objectName","entryId"]},
191
192
  {"id":"crm.notes.list","group":"crm","summary":"List a CRM entry's notes (titled, document-style comments), newest first.","cli":"dench crm notes list","method":"GET","path":"/crm/objects/{objectName}/entries/{entryId}/notes","permission":"crm:read","pathParams":["objectName","entryId"]},
@@ -1625,6 +1625,25 @@ const rawApiOperations = [
1625
1625
  }),
1626
1626
  },
1627
1627
  }),
1628
+ op({
1629
+ id: "crm.context.get",
1630
+ group: "crm",
1631
+ summary:
1632
+ "Read-only source diagnostics: accessible evidence, association reasons, last Brief source manifest, generation queue, and your mailbox delivery health. Bounded, cursor-paged snapshot; does not certify complete history.",
1633
+ cli: "dench crm context",
1634
+ method: "GET",
1635
+ path: "/crm/objects/{objectName}/entries/{entryId}/context",
1636
+ requestSchema: noBody,
1637
+ responseSchema: anyResponse,
1638
+ backend: {
1639
+ ...convex("query", "functions/crm/contextDiagnostics:getForEntry"),
1640
+ transformArgs: (input) => ({
1641
+ objectName: input.objectName,
1642
+ entryId: input.entryId,
1643
+ ...(typeof input.cursor === "string" ? { cursor: input.cursor } : {}),
1644
+ }),
1645
+ },
1646
+ }),
1628
1647
  op({
1629
1648
  id: "crm.brief.regenerate",
1630
1649
  group: "crm",
@@ -195,6 +195,7 @@ export type SignalRow = {
195
195
  personName?: string;
196
196
  personTitle?: string;
197
197
  personLinkedinUrl?: string;
198
+ personAvatarUrl?: string;
198
199
  term?: string;
199
200
  postUrl?: string;
200
201
  postText?: string;
@@ -1677,6 +1678,7 @@ export type SignalBuyer = {
1677
1678
  firstName?: string;
1678
1679
  title?: string;
1679
1680
  linkedinUrl?: string;
1681
+ avatarUrl?: string;
1680
1682
  email?: string;
1681
1683
  };
1682
1684
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dench.com/cli",
3
- "version": "3.6.1-staging.362",
3
+ "version": "3.6.3-staging.372",
4
4
  "description": "Dench agent workspace CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31,6 +31,7 @@
31
31
  "chat-spawn.ts",
32
32
  "crm.ts",
33
33
  "crm-comments.ts",
34
+ "crm-context.ts",
34
35
  "crm-analytics.ts",
35
36
  "crm-detections.ts",
36
37
  "crm-privacy.ts",