@graph8/sdk 0.358.0 → 0.362.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.
Files changed (110) hide show
  1. package/blocks/_foundation/README.md +108 -0
  2. package/blocks/_foundation/block.json +160 -12
  3. package/blocks/_foundation/components/api-error.tsx +62 -18
  4. package/blocks/_foundation/components/empty-state.tsx +39 -7
  5. package/blocks/_foundation/components/screen/bar-list.tsx +71 -0
  6. package/blocks/_foundation/components/screen/detail-panel.tsx +114 -0
  7. package/blocks/_foundation/components/screen/entity-avatar.tsx +56 -0
  8. package/blocks/_foundation/components/screen/form-sheet.tsx +73 -0
  9. package/blocks/_foundation/components/screen/index.ts +21 -0
  10. package/blocks/_foundation/components/screen/key-value-list.tsx +65 -0
  11. package/blocks/_foundation/components/screen/screen-layout.tsx +124 -0
  12. package/blocks/_foundation/components/screen/section-card.tsx +47 -0
  13. package/blocks/_foundation/components/screen/sparkline.tsx +77 -0
  14. package/blocks/_foundation/components/screen/split-view.tsx +125 -0
  15. package/blocks/_foundation/components/screen/stat-strip.tsx +121 -0
  16. package/blocks/_foundation/components/screen/status-pill.tsx +104 -0
  17. package/blocks/_foundation/components/screen/time-series-chart.tsx +114 -0
  18. package/blocks/_foundation/components/screen/toolbar.tsx +144 -0
  19. package/blocks/_foundation/hooks/use-url-state.ts +74 -0
  20. package/blocks/appointments/README.md +21 -1
  21. package/blocks/appointments/block.json +39 -2
  22. package/blocks/appointments/components/event-type-related.tsx +75 -0
  23. package/blocks/appointments/components/meeting-list.tsx +8 -4
  24. package/blocks/appointments/components/meetings-screen.tsx +154 -0
  25. package/blocks/appointments/components/scheduling-screen.tsx +121 -0
  26. package/blocks/appointments/hooks/use-event-types.ts +17 -0
  27. package/blocks/block.types.ts +9 -0
  28. package/blocks/deals/README.md +34 -3
  29. package/blocks/deals/block.json +39 -4
  30. package/blocks/deals/components/deal-detail.tsx +4 -2
  31. package/blocks/deals/components/deal-related.tsx +87 -0
  32. package/blocks/deals/components/deals-screen.tsx +293 -0
  33. package/blocks/deals/components/pipeline-board.tsx +4 -2
  34. package/blocks/deals/hooks/use-default-owner.ts +60 -0
  35. package/blocks/deals/lib/deals-types.ts +14 -0
  36. package/blocks/forms/README.md +12 -0
  37. package/blocks/forms/block.json +9 -1
  38. package/blocks/forms/components/forms-screen.tsx +350 -0
  39. package/blocks/forms/components/submissions-table.tsx +13 -5
  40. package/blocks/lifecycle/README.md +16 -0
  41. package/blocks/lifecycle/block.json +23 -1
  42. package/blocks/lifecycle/components/account-related.tsx +66 -0
  43. package/blocks/lifecycle/components/lifecycle-screen.tsx +147 -0
  44. package/blocks/newsletter/README.md +13 -0
  45. package/blocks/newsletter/block.json +9 -1
  46. package/blocks/newsletter/components/newsletter-screen.tsx +402 -0
  47. package/blocks/newsletter/components/subscriber-table.tsx +12 -6
  48. package/blocks/nurture/README.md +12 -0
  49. package/blocks/nurture/block.json +9 -1
  50. package/blocks/nurture/components/nurture-screen.tsx +279 -0
  51. package/blocks/pages/README.md +12 -0
  52. package/blocks/pages/block.json +9 -1
  53. package/blocks/pages/components/content-library.tsx +37 -7
  54. package/blocks/pages/components/page-list.tsx +4 -2
  55. package/blocks/pages/components/pages-screen.tsx +154 -0
  56. package/blocks/quotes/README.md +17 -0
  57. package/blocks/quotes/block.json +26 -2
  58. package/blocks/quotes/components/quote-list.tsx +7 -3
  59. package/blocks/quotes/components/quote-related.tsx +120 -0
  60. package/blocks/quotes/components/quotes-screen.tsx +169 -0
  61. package/dist/cli.js +197 -37
  62. package/dist/index.browser.js +1 -1
  63. package/dist/index.browser.js.map +1 -1
  64. package/dist/index.browser.mjs +1 -1
  65. package/dist/index.browser.mjs.map +1 -1
  66. package/dist/index.d.mts +93 -7
  67. package/dist/index.d.ts +93 -7
  68. package/dist/index.js +1 -1
  69. package/dist/index.js.map +1 -1
  70. package/dist/index.mjs +1 -1
  71. package/dist/index.mjs.map +1 -1
  72. package/dist/react.browser.js +1 -1
  73. package/dist/react.browser.js.map +1 -1
  74. package/dist/react.browser.mjs +1 -1
  75. package/dist/react.browser.mjs.map +1 -1
  76. package/dist/react.d.mts +90 -4
  77. package/dist/react.d.ts +90 -4
  78. package/dist/react.js +1 -1
  79. package/dist/react.js.map +1 -1
  80. package/dist/react.mjs +1 -1
  81. package/dist/react.mjs.map +1 -1
  82. package/dist/types/blocks/create.d.ts +15 -1
  83. package/dist/types/blocks/doctor.d.ts +2 -1
  84. package/dist/types/blocks/flows.d.ts +20 -0
  85. package/dist/types/blocks/registry.d.ts +15 -0
  86. package/dist/types/core.d.ts +3 -2
  87. package/dist/types/react.d.ts +2 -0
  88. package/dist/types/studio.d.ts +48 -0
  89. package/dist/types/version.d.ts +2 -2
  90. package/docs/api/adCampaigns.d.ts +4 -0
  91. package/docs/api/adCampaigns.md +4 -0
  92. package/docs/api/gtmCampaigns.d.ts +4 -0
  93. package/docs/api/gtmCampaigns.md +2 -0
  94. package/docs/api/gtmContext.d.ts +5 -1
  95. package/docs/api/gtmContext.md +15 -7
  96. package/docs/api/integrations.d.ts +29 -4
  97. package/docs/api/integrations.md +14 -0
  98. package/docs/sdk-clients.md +1 -1
  99. package/package.json +1 -1
  100. package/stacks/stack.schema.json +6 -1
  101. package/styles/styles.css +1 -1
  102. package/templates/next-app/README.md.tmpl +16 -0
  103. package/templates/next-app/app/globals.css.tmpl +105 -0
  104. package/templates/next-app/app/layout.tsx.tmpl +11 -2
  105. package/templates/next-app/components/app-shell.tsx.tmpl +238 -23
  106. package/templates/next-app/components/shell/connection-status.tsx.tmpl +109 -0
  107. package/templates/next-app/components/shell/nav-model.ts.tmpl +65 -0
  108. package/templates/next-app/components/shell/quick-jump.tsx.tmpl +131 -0
  109. package/templates/next-app/components/shell/theme-toggle.tsx.tmpl +40 -0
  110. package/templates/next-app/lib/nav.ts.tmpl +1 -1
@@ -8,7 +8,7 @@
8
8
  * block registry; writes only inside `<dir>`.
9
9
  */
10
10
  import { type AddIO, type PackageManager } from "./add";
11
- import { type Registry, type Stack } from "./registry";
11
+ import { type Registry, type Stack, type StackNav } from "./registry";
12
12
  export declare const CREATE_USAGE = "Usage: npx @graph8/sdk create <stack> <dir> [options]\n\nScaffold a Next.js (App Router, TypeScript, Tailwind CSS v4) app for a stack and\ninstall the stack's blocks into it. Run `graph8-sdk list` to see the stacks.\n --package-manager <npm|pnpm|yarn|bun> default: the one running the command, else npm\n --no-install write the files and blocks, do not install dependencies\n --dry-run print what would be written, write and install nothing\n --force allow a non-empty <dir> (template files are overwritten, and graph8.json\n is reset: blocks you added to that app earlier are no longer recorded)\nThen: set G8_API_KEY in <dir>/.env.local and run `npx @graph8/sdk doctor --stack <stack>`.";
13
13
  export interface CreateOptions {
14
14
  stack: string;
@@ -40,6 +40,20 @@ interface OutFile {
40
40
  export declare function pageFileFor(navPath: string): string;
41
41
  /** Why this stack cannot be scaffolded, or null. */
42
42
  export declare function stackProblem(reg: Registry, stack: Stack): string | null;
43
+ /** Absolute path of a nav entry's hand-written page template, or null when it uses the generic route page. */
44
+ export declare function stackPageFile(reg: Registry, stack: Stack, n: StackNav): string | null;
45
+ /** True when any nav entry uses `icon`, `group` or `description`. */
46
+ export declare function navUsesExtras(stack: Stack): boolean;
47
+ /**
48
+ * The three pieces of `lib/nav.ts`. A stack that uses none of the optional nav fields gets exactly the
49
+ * plain `{ label, path }[]` file it always did; otherwise a typed `NavItem[]` whose icons are real
50
+ * lucide-react imports (only the ones used).
51
+ */
52
+ export declare function navParts(stack: Stack): {
53
+ navImports: string;
54
+ navType: string;
55
+ navJson: string;
56
+ };
43
57
  export declare function planCreate(reg: Registry, stack: Stack, appName: string, pm: PackageManager, io: CreateIO): OutFile[];
44
58
  /** Run `create`. Returns the process exit code. */
45
59
  export declare function runCreate(opts: CreateOptions, reg: Registry, io: CreateIO, cwd: string): number;
@@ -7,11 +7,12 @@
7
7
  * never printed, not even in an error.
8
8
  */
9
9
  import { type Registry } from "./registry";
10
- export declare const DOCTOR_USAGE = "Usage: npx @graph8/sdk doctor [--stack <id>] [--blocks a,b] [--dir <path>]\n\nCheck that this project is ready for graph8 blocks:\n - G8_API_KEY (env or .env.local) is valid\n - the key's scopes cover the blocks you chose\n - the organization's subscription is active\n - a checklist of in-app setup each block needs\nWith no --stack/--blocks, the blocks recorded in graph8.json are checked.\nOptional G8_API_URL points at a non-default API. Exit code 0 when all checks\npass, 1 otherwise.";
10
+ export declare const DOCTOR_USAGE = "Usage: npx @graph8/sdk doctor [--stack <id>] [--blocks a,b] [--dir <path>] [--strict]\n\nCheck that this project is ready for graph8 blocks:\n - G8_API_KEY (env or .env.local) is valid\n - the key's scopes cover the blocks you chose\n - the organization's subscription is active\n - a checklist of in-app setup each block needs\nWith --stack it also lists \"Flows\": block components that no page of the stack reaches\n(a warning; --strict makes them fail the run).\nWith no --stack/--blocks, the blocks recorded in graph8.json are checked.\nOptional G8_API_URL points at a non-default API. Exit code 0 when all checks\npass, 1 otherwise.";
11
11
  export interface DoctorOptions {
12
12
  stack?: string;
13
13
  blocks: string[];
14
14
  dir: string;
15
+ strict?: boolean;
15
16
  }
16
17
  export declare function parseDoctorArgs(argv: string[]): DoctorOptions;
17
18
  export interface DoctorIO {
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Flow reachability for `graph8-sdk doctor --stack <id>`.
3
+ *
4
+ * A generated app is only as useful as the components its pages reach. This walks
5
+ * the imports from every page the stack generates (the nav component, or a
6
+ * hand-written page template's imports), through the block sources, and reports the
7
+ * block components nothing reaches: a flow the block ships but the app never shows.
8
+ *
9
+ * Node only. Reads block sources and stack page templates; writes nothing.
10
+ */
11
+ import { type Registry, type Stack } from "./registry";
12
+ export interface UnreachedComponent {
13
+ block: string;
14
+ component: string;
15
+ }
16
+ /**
17
+ * Components of the stack's own blocks (the foundation's shared UI is exempt) that no
18
+ * generated page reaches, directly or through a Screen that imports them.
19
+ */
20
+ export declare function unreachedComponents(reg: Registry, stack: Stack): UnreachedComponent[];
@@ -75,6 +75,14 @@ export interface StackNav {
75
75
  component: string;
76
76
  /** JSON props the route passes to the component. */
77
77
  props?: Record<string, unknown>;
78
+ /** lucide-react export name shown beside the label in the sidebar. */
79
+ icon?: string;
80
+ /** Sidebar section label; entries with the same group sit together. */
81
+ group?: string;
82
+ /** One line about the screen (tooltips, a home grid). */
83
+ description?: string;
84
+ /** Hand-written page template, relative to `stacks/<stack-id>/` (`pages/*.tsx.tmpl`), used instead of the generic route page. */
85
+ page?: string;
78
86
  }
79
87
  export interface Stack {
80
88
  id: string;
@@ -84,10 +92,14 @@ export interface Stack {
84
92
  status: "available" | "planned";
85
93
  blocks: string[];
86
94
  nav: StackNav[];
95
+ /** A nav path that `/` redirects to (default: `/` itself when it is a nav entry, else the first entry). */
96
+ home?: string;
87
97
  }
88
98
  export interface Registry {
89
99
  blocks: Block[];
90
100
  stacks: Stack[];
101
+ /** Directory holding `<stack-id>.json` and `<stack-id>/pages/*`. Set by `loadRegistry`. */
102
+ stacksRoot?: string;
91
103
  }
92
104
  /**
93
105
  * Load every block under `<blocksRoot>` and every stack under the sibling
@@ -105,7 +117,10 @@ export declare function resolveWithDeps(reg: Registry, ids: string[]): Block[];
105
117
  export declare function searchBlocks(reg: Registry, text: string): Block[];
106
118
  /** Stacks matching the same way (id, title, summary). */
107
119
  export declare function searchStacks(reg: Registry, text: string): Stack[];
120
+ /** Finished screens of a block: components named `<Something>Screen`. Customer agents should reach for these first. */
121
+ export declare function screenNames(b: Block): string[];
108
122
  export declare function blockSummary(b: Block): {
123
+ screens?: string[] | undefined;
109
124
  id: string;
110
125
  title: string;
111
126
  summary: string;
@@ -888,6 +888,8 @@ declare class G8 {
888
888
  category?: string;
889
889
  limit?: number;
890
890
  include_content?: boolean;
891
+ include_intelligence?: boolean;
892
+ include_research?: boolean;
891
893
  }): Promise<{
892
894
  data: import("./studio").GlobalContextDocument[];
893
895
  }>;
@@ -899,8 +901,7 @@ declare class G8 {
899
901
  }>;
900
902
  personas(params?: {
901
903
  status?: string;
902
- limit
903
- /** @internal */ ? /** @internal */: number;
904
+ limit?: number;
904
905
  }): Promise<{
905
906
  data: import("./studio").Persona[];
906
907
  }>;
@@ -824,6 +824,8 @@ export declare const useG8: () => {
824
824
  category?: string;
825
825
  limit?: number;
826
826
  include_content?: boolean;
827
+ include_intelligence?: boolean;
828
+ include_research?: boolean;
827
829
  }): Promise<{
828
830
  data: import("./studio").GlobalContextDocument[];
829
831
  }>;
@@ -6,6 +6,18 @@ export interface GlobalContextDocument {
6
6
  metadata: Record<string, unknown> | null;
7
7
  created_at: string | null;
8
8
  updated_at: string | null;
9
+ /** Fields the endpoint actually returns (the ones above predate them). */
10
+ display_name?: string | null;
11
+ file_type?: string | null;
12
+ folder_path?: string | null;
13
+ status?: string | null;
14
+ priority?: number | null;
15
+ version?: string | number | null;
16
+ /** The group the Studio Wiki shows the document under (TAM / ICP / Persona
17
+ * Research are stored as market/audience but shown under "targeting"). */
18
+ wiki_category?: string;
19
+ /** Which Wiki bucket the row came from. */
20
+ workflow?: "context" | "intelligence" | "research";
9
21
  }
10
22
  export interface Persona {
11
23
  id: string;
@@ -16,6 +28,20 @@ export interface Persona {
16
28
  goals: string[];
17
29
  channels: string[];
18
30
  created_at: string | null;
31
+ /** Fields GET /personas actually returns (cb_personas columns). The persona's
32
+ * name is `title`, its "why" is `why_target`, its signals are `key_signals`. */
33
+ title?: string | null;
34
+ why_target?: string | null;
35
+ key_signals?: unknown[];
36
+ campaign_approach?: string | null;
37
+ recommended_goal?: string | null;
38
+ expected_receptivity?: string | null;
39
+ confidence?: string | null;
40
+ confidence_score?: number | null;
41
+ priority?: number | null;
42
+ pinned?: boolean | null;
43
+ source?: string | null;
44
+ updated_at?: string | null;
19
45
  }
20
46
  export interface ICP {
21
47
  id: string;
@@ -29,6 +55,24 @@ export interface ICP {
29
55
  revenue_max: number | null;
30
56
  countries: string[] | null;
31
57
  created_at: string | null;
58
+ /** Fields GET /icps actually returns (cb_icps columns). Industries and
59
+ * company sizes live in `firmographics.industries` / `firmographics.company_sizes`. */
60
+ firmographics?: {
61
+ industries?: string[];
62
+ company_sizes?: string[];
63
+ revenue_ranges?: string[];
64
+ geographies?: string[];
65
+ [key: string]: unknown;
66
+ };
67
+ tech_stack?: Record<string, unknown>;
68
+ buying_signals?: unknown[];
69
+ fit_score?: number | null;
70
+ opportunity_score?: number | null;
71
+ readiness_score?: number | null;
72
+ total_score?: number | null;
73
+ pinned?: boolean | null;
74
+ priority?: number | null;
75
+ updated_at?: string | null;
32
76
  }
33
77
  export interface IntelligenceData {
34
78
  id: string;
@@ -67,6 +111,10 @@ export declare const createStudioClient: (apiKey: string, apiUrl?: string) => {
67
111
  category?: string;
68
112
  limit?: number;
69
113
  include_content?: boolean;
114
+ /** Also list the Wiki's Intelligence documents (metadata only). */
115
+ include_intelligence?: boolean;
116
+ /** Also list the Wiki's Research reports. */
117
+ include_research?: boolean;
70
118
  }): Promise<{
71
119
  data: GlobalContextDocument[];
72
120
  }>;
@@ -5,6 +5,6 @@
5
5
  * both together (the version-parity gate already pins package.json, the
6
6
  * lockfile and the CHANGELOG to each other).
7
7
  */
8
- export declare const SDK_VERSION = "0.358.0";
8
+ export declare const SDK_VERSION = "0.362.0";
9
9
  /** Value of the `X-G8-Client` header every SDK request carries (I-13). */
10
- export declare const SDK_CLIENT_ID = "js-sdk/0.358.0";
10
+ export declare const SDK_CLIENT_ID = "js-sdk/0.362.0";
@@ -425,10 +425,14 @@ export interface AdCampaignResponse {
425
425
  launched_at?: string | null;
426
426
  name: string;
427
427
  objective?: string | null;
428
+ /** True when end_date is before today (UTC). Null when the campaign has no end date. */
429
+ past_end_date?: boolean | null;
428
430
  platform: string;
429
431
  platform_campaign_id?: string | null;
430
432
  start_date?: string | null;
431
433
  status: string;
434
+ /** Plain-language note when the stored status cannot be taken at face value, e.g. the end date has passed but the status still says pending. Null otherwise. */
435
+ status_note?: string | null;
432
436
  sync_config_id: number;
433
437
  }
434
438
 
@@ -324,8 +324,10 @@ Other envelope fields: `pagination` (PaginationMeta).
324
324
  | `google_campaign_subtype` | `string \| null` | no | |
325
325
  | `launched_at` | `string \| null` | no | |
326
326
  | `objective` | `string \| null` | no | |
327
+ | `past_end_date` | `boolean \| null` | no | True when end_date is before today (UTC). Null when the campaign has no end date. |
327
328
  | `platform_campaign_id` | `string \| null` | no | |
328
329
  | `start_date` | `string \| null` | no | |
330
+ | `status_note` | `string \| null` | no | Plain-language note when the stored status cannot be taken at face value, e.g. the end date has passed but the status still says pending. Null otherwise. |
329
331
 
330
332
  **Example**
331
333
 
@@ -598,8 +600,10 @@ Other envelope fields: `pagination` (PaginationMeta).
598
600
  | `google_campaign_subtype` | `string \| null` | no | |
599
601
  | `launched_at` | `string \| null` | no | |
600
602
  | `objective` | `string \| null` | no | |
603
+ | `past_end_date` | `boolean \| null` | no | True when end_date is before today (UTC). Null when the campaign has no end date. |
601
604
  | `platform_campaign_id` | `string \| null` | no | |
602
605
  | `start_date` | `string \| null` | no | |
606
+ | `status_note` | `string \| null` | no | Plain-language note when the stored status cannot be taken at face value, e.g. the end date has passed but the status still says pending. Null otherwise. |
603
607
 
604
608
  **Example**
605
609
 
@@ -529,6 +529,8 @@ export interface CampaignFullPatchRequest {
529
529
  primary_hook?: string | null;
530
530
  /** If provided, replaces the sequence step ordering (same as PUT /sequence). */
531
531
  sequence_steps?: Array<SequenceStepRef> | null;
532
+ /** Replace the campaign's channels (email, linkedin, phone, voice_ai, sms). Omit to leave them unchanged. Same as PATCH /campaigns/{id}. */
533
+ target_channels?: Array<string> | null;
532
534
  target_persona?: string | null;
533
535
  /** Sequence IDs to UNLINK from this campaign. DELETEs ONLY rows where status='linked'. Launch-audit rows (status='pushed'/'superseded'/'failed') are never touched — those are an immutable historical record. */
534
536
  unlink_sequence_ids?: Array<string> | null;
@@ -659,6 +661,8 @@ export interface developer_api__interfaces__v1__gtm_campaigns_router__CampaignUp
659
661
  name?: string | null;
660
662
  /** Primary hook text */
661
663
  primary_hook?: string | null;
664
+ /** Replace the campaign's channels, e.g. ['email','linkedin']. Accepted values: email, linkedin, phone, voice_ai, sms. Omit to leave them unchanged. Existing documents and steps are not deleted. */
665
+ target_channels?: Array<string> | null;
662
666
  /** Target persona */
663
667
  target_persona?: string | null;
664
668
  }
@@ -816,6 +816,7 @@ Body fields (`CampaignFullPatchRequest`):
816
816
  | `body.name` | `string \| null` | no | max length 255 |
817
817
  | `body.primary_hook` | `string \| null` | no | |
818
818
  | `body.sequence_steps` | `Array<SequenceStepRef> \| null` | no | If provided, replaces the sequence step ordering (same as PUT /sequence). |
819
+ | `body.target_channels` | `Array<string> \| null` | no | Replace the campaign's channels (email, linkedin, phone, voice_ai, sms). Omit to leave them unchanged. Same as PATCH /campaigns/{id}. |
819
820
  | `body.target_persona` | `string \| null` | no | max length 200 |
820
821
  | `body.unlink_sequence_ids` | `Array<string> \| null` | no | Sequence IDs to UNLINK from this campaign. DELETEs ONLY rows where status='linked'. Launch-audit rows (status='pushed'/'superseded'/'failed') are never touched — those are an immutable historical record. |
821
822
 
@@ -862,6 +863,7 @@ Body fields (`developer_api__interfaces__v1__gtm_campaigns_router__CampaignUpdat
862
863
  | `body.goal` | `string \| null` | no | Campaign goal max length 255 |
863
864
  | `body.name` | `string \| null` | no | Campaign name max length 255 |
864
865
  | `body.primary_hook` | `string \| null` | no | Primary hook text |
866
+ | `body.target_channels` | `Array<string> \| null` | no | Replace the campaign's channels, e.g. ['email','linkedin']. Accepted values: email, linkedin, phone, voice_ai, sms. Omit to leave them unchanged. Existing documents and steps are not deleted. |
865
867
  | `body.target_persona` | `string \| null` | no | Target persona max length 200 |
866
868
 
867
869
  **Returns** `ApiResponse_dict_`: the envelope `{ data: Record<string, unknown>, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
@@ -399,10 +399,14 @@ export interface GtmContextOperations {
399
399
  list_global_context_documents_global_context_documents_get: {
400
400
  input: {
401
401
  query?: {
402
- /** Filter by context category */
402
+ /** Filter by context category: brand, audience, messaging, market, offer, targeting, data (case-insensitive). `targeting` matches the Studio Wiki's Targeting group (TAM / ICP / Persona Research). An unknown category that matches no document returns 422 listing the valid categories. */
403
403
  category?: string | null;
404
404
  /** Include each document's body text at `content` (read from meta_data.content). Default True preserves historical behavior (this endpoint has always returned content); pass false for a lighter metadata-only listing. */
405
405
  include_content?: boolean;
406
+ /** Also list the Wiki's Intelligence documents (website scrape, competitor discovery, organic keywords, brand news, ...) with `workflow`='intelligence' and category 'data'. Metadata only: read a body with GET /intelligence-data ?data_type=<file_type>&include_content=true. Default false (historical shape). */
407
+ include_intelligence?: boolean;
408
+ /** Also list the Wiki's Research reports with `workflow`='research' and category 'data'; `content` carries the report markdown when include_content is true. Default false (historical shape). */
409
+ include_research?: boolean;
406
410
  limit?: number;
407
411
  };
408
412
  headers?: {
@@ -915,21 +915,29 @@ const result = await g8.api.gtmContext.listActivities();
915
915
  List global context documents for the authenticated organization.
916
916
 
917
917
  Each row carries metadata (id, display_name, file_type, category,
918
- folder_path, status, priority, version, timestamps). When
919
- ``include_content`` is True (the default) the document body is included at
920
- ``content`` (sourced from ``meta_data.content``) so callers can read what a
921
- document actually says; pass ``include_content=false`` to omit the body for
922
- a cheaper listing. The default stays True for backwards compatibility — the
923
- MCP ``g8_gtm_get_global_context`` tool, the JS SDK ``studio.globalContext``
918
+ folder_path, status, priority, version, timestamps), plus `wiki_category`
919
+ (the group the Studio Wiki shows it under) and `workflow` (context,
920
+ intelligence or research). When ``include_content`` is True (the default)
921
+ the document body is included at ``content`` (sourced from
922
+ ``meta_data.content``) so callers can read what a document actually says;
923
+ pass ``include_content=false`` to omit the body for a cheaper listing. The
924
+ default stays True for backwards compatibility — the MCP
925
+ ``g8_gtm_get_global_context`` tool, the JS SDK ``studio.globalContext``
924
926
  client, and the ``g8://global-context`` resource surfaces have always relied
925
927
  on ``content`` being present.
926
928
 
929
+ ``include_intelligence`` / ``include_research`` add the Wiki's other two
930
+ buckets so a caller can see every Wiki document in one call; ``limit``
931
+ applies to each bucket.
932
+
927
933
  **Input**
928
934
 
929
935
  | Field | Type | Required | Description |
930
936
  |---|---|---|---|
931
- | `query.category` | `string \| null` | no | Filter by context category |
937
+ | `query.category` | `string \| null` | no | Filter by context category: brand, audience, messaging, market, offer, targeting, data (case-insensitive). `targeting` matches the Studio Wiki's Targeting group (TAM / ICP / Persona Research). An unknown category that matches no document returns 422 listing the valid categories. |
932
938
  | `query.include_content` | `boolean` | no | Include each document's body text at `content` (read from meta_data.content). Default True preserves historical behavior (this endpoint has always returned content); pass false for a lighter metadata-only listing. default `true` |
939
+ | `query.include_intelligence` | `boolean` | no | Also list the Wiki's Intelligence documents (website scrape, competitor discovery, organic keywords, brand news, ...) with `workflow`='intelligence' and category 'data'. Metadata only: read a body with GET /intelligence-data ?data_type=<file_type>&include_content=true. Default false (historical shape). default `false` |
940
+ | `query.include_research` | `boolean` | no | Also list the Wiki's Research reports with `workflow`='research' and category 'data'; `content` carries the report markdown when include_content is true. Default false (historical shape). default `false` |
933
941
  | `query.limit` | `integer` | no | default `50` |
934
942
 
935
943
  **Returns** `ApiResponse_list_dict__`: the envelope `{ data: Array<Record<string, unknown>>, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
@@ -1549,7 +1549,7 @@ export interface IntegrationsOperations {
1549
1549
  };
1550
1550
  }
1551
1551
 
1552
- // 64 schemas referenced above (the same as G8Contract.<Name>).
1552
+ // 65 schemas referenced above (the same as G8Contract.<Name>).
1553
1553
 
1554
1554
  /**
1555
1555
  * A list of ad-platform objects.
@@ -1653,14 +1653,19 @@ export interface BatchGetByEmailRequest {
1653
1653
  * This is the irreversible half: records begin landing in graph8 and a
1654
1654
  * migration cannot be un-run, only cancelled part-way.
1655
1655
  *
1656
- * Both fields are OPTIONAL and omitting them accepts the discovery as
1656
+ * Every field is OPTIONAL and omitting them accepts the discovery as
1657
1657
  * proposed - which is the point of previewing it first. Send
1658
- * `field_mappings_override` to change where a CRM field lands, or
1659
- * `selected_list_ids` to import only some lists.
1658
+ * `field_mappings_override` to change where a CRM field lands,
1659
+ * `selected_list_ids` to import only some lists, or `owner_decisions` to say
1660
+ * what happens to the records of Salesforce owners who are not in graph8.
1661
+ * A Salesforce discovery with an `unmatched` owner needs a decision for that
1662
+ * owner: without one the confirm is refused with 422.
1660
1663
  */
1661
1664
  export interface ConfirmMigrationRequest {
1662
1665
  /** Per entity type, the mappings to use instead of the discovered ones. Omit to accept what discovery proposed. */
1663
1666
  field_mappings_override?: Record<string, Array<Record<string, unknown>>> | null;
1667
+ /** Salesforce only: one decision per record owner who is not a graph8 member (at most 500). Required for every owner whose `match.status` is `unmatched`; optional `assign` for a `placeholder` owner. `match` moves every record the owner has; `assign` moves only their open deals and open tasks. */
1668
+ owner_decisions?: Array<MigrationOwnerDecision> | null;
1664
1669
  /** Import only these CRM lists. Omit to take every discovered list. */
1665
1670
  selected_list_ids?: Array<string> | null;
1666
1671
  }
@@ -2025,6 +2030,26 @@ export interface LeadUpdateRequest {
2025
2030
  website?: string | null;
2026
2031
  }
2027
2032
 
2033
+ /**
2034
+ * What happens to the records of one Salesforce record owner who is not a graph8 member.
2035
+ *
2036
+ * Discovery lists every record owner in the status's `owners`, each with a
2037
+ * `match.status`. An owner whose status is `unmatched` needs a decision, or
2038
+ * the confirm is refused with 422. An owner whose status is `placeholder`
2039
+ * (inactive in Salesforce, a rep who left) may only be assigned; without a
2040
+ * decision their records stay on the placeholder, as history.
2041
+ */
2042
+ export interface MigrationOwnerDecision {
2043
+ /** `invite`: invite the owner to graph8 by email; their records are held for the invited address and become theirs when they first sign in. Invites go out in a member's name, so an API key's confirm with an `invite` decision is refused with 403. `assign`: move only their OPEN deals and OPEN tasks to the graph8 member `assign_to_team_member_id`; contacts, companies and closed records stay on the owner's placeholder. `match`: this Salesforce user IS the graph8 member `assign_to_team_member_id`; EVERY record they own moves to that member. `unassigned`: import their records with no owner. */
2044
+ action: "invite" | "assign" | "unassigned" | "match";
2045
+ /** `assign` and `match` only: the graph8 team member id who receives the records. */
2046
+ assign_to_team_member_id?: string | null;
2047
+ /** `invite` only: the address to invite. Omit to use the owner's Salesforce email. */
2048
+ invite_email?: string | null;
2049
+ /** The owner's Salesforce user id, as discovery listed it in `owners`. */
2050
+ sf_user_id: string;
2051
+ }
2052
+
2028
2053
  /**
2029
2054
  * Add and/or remove contacts from one CRM list, in a single call.
2030
2055
  *
@@ -268,6 +268,7 @@ Body fields (`ConfirmMigrationRequest`):
268
268
  | Field | Type | Required | Description |
269
269
  |---|---|---|---|
270
270
  | `body.field_mappings_override` | `Record<string, Array<Record<string, unknown>>> \| null` | no | Per entity type, the mappings to use instead of the discovered ones. Omit to accept what discovery proposed. |
271
+ | `body.owner_decisions` | `Array<MigrationOwnerDecision> \| null` | no | Salesforce only: one decision per record owner who is not a graph8 member (at most 500). Required for every owner whose `match.status` is `unmatched`; optional `assign` for a `placeholder` owner. `match` moves every record the owner has; `assign` moves only their open deals and open tasks. max items 500 |
271
272
  | `body.selected_list_ids` | `Array<string> \| null` | no | Import only these CRM lists. Omit to take every discovered list. |
272
273
 
273
274
  **Returns** `ApiResponse_ConnectionPayload_`: the envelope `{ data: ConnectionPayload, ... }`. `g8.api` returns the envelope as-is, so read `result.data`.
@@ -3789,3 +3790,16 @@ One provider-side custom field. `field_name` is the CRM's API name, not its labe
3789
3790
  |---|---|---|---|
3790
3791
  | `phone` | `string` | yes | |
3791
3792
  | `phone_type` | `string \| null` | no | |
3793
+
3794
+ <a id="type-migrationownerdecision"></a>
3795
+
3796
+ ### `MigrationOwnerDecision`
3797
+
3798
+ What happens to the records of one Salesforce record owner who is not a graph8 member. Discovery lists every record owner in the status's `owners`, each with a `match.status`. An owner whose status is `unmatched` needs a decision, or the confirm is refused with 422. An owner whose status is `placeholder` (inactive in Salesforce, a rep who left) may only be assigned; without a decision their records stay on the placeholder, as history.
3799
+
3800
+ | Field | Type | Required | Description |
3801
+ |---|---|---|---|
3802
+ | `action` | `"invite" \| "assign" \| "unassigned" \| "match"` | yes | `invite`: invite the owner to graph8 by email; their records are held for the invited address and become theirs when they first sign in. Invites go out in a member's name, so an API key's confirm with an `invite` decision is refused with 403. `assign`: move only their OPEN deals and OPEN tasks to the graph8 member `assign_to_team_member_id`; contacts, companies and closed records stay on the owne… |
3803
+ | `sf_user_id` | `string` | yes | The owner's Salesforce user id, as discovery listed it in `owners`. min length 1, max length 64 |
3804
+ | `assign_to_team_member_id` | `string \| null` | no | `assign` and `match` only: the graph8 team member id who receives the records. max length 64 |
3805
+ | `invite_email` | `string \| null` | no | `invite` only: the address to invite. Omit to use the owner's Salesforce email. max length 320 |
@@ -3593,7 +3593,7 @@ Create a buyer persona manually (no AI generation). Requires title + website_url
3593
3593
  ### `g8.studio.globalContext`
3594
3594
 
3595
3595
  ```ts
3596
- g8.studio.globalContext: (params?: { category?: string; limit?: number; include_content?: boolean; }) => Promise<{ data: GlobalContextDocument[]; }>
3596
+ g8.studio.globalContext: (params?: { category?: string; limit?: number; include_content?: boolean; include_intelligence?: boolean; include_research?: boolean; }) => Promise<{ data: GlobalContextDocument[]; }>
3597
3597
  ```
3598
3598
 
3599
3599
  Org-level Studio documents (brand_brief, value_props, messaging_house, etc.). `include_content` defaults to true server-side, so each document includes its `content` body unless you explicitly pass `include_content: false`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graph8/sdk",
3
- "version": "0.358.0",
3
+ "version": "0.362.0",
4
4
  "description": "graph8 SDK - CRM, enrichment, sequences, campaigns, and tracking for B2B",
5
5
  "license": "MIT",
6
6
  "author": "graph8 <support@graph8.com> (https://graph8.com)",
@@ -13,6 +13,7 @@
13
13
  "summary": { "type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[^\\n]+$" },
14
14
  "status": { "enum": ["available", "planned"], "default": "available", "description": "available: every block exists in blocks/, `create` can scaffold it, and CI checks every reference. planned: some blocks are still being built; CI skips the block references and `create` refuses with the missing blocks. Optional, default available." },
15
15
  "blocks": { "type": "array", "items": { "type": "string", "pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$" }, "uniqueItems": true, "minItems": 1, "description": "Install order: every block's dependencies come earlier." },
16
+ "home": { "type": "string", "pattern": "^/[A-Za-z0-9/_\\-]*$", "description": "Optional nav path that `/` redirects to. Default: `/` when it is a nav entry, else the first entry." },
16
17
  "nav": {
17
18
  "type": "array",
18
19
  "items": {
@@ -24,7 +25,11 @@
24
25
  "path": { "type": "string", "pattern": "^/[A-Za-z0-9/_\\-]*$", "description": "A static route; it is a sidebar link, so no dynamic [segments]." },
25
26
  "block": { "type": "string", "pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$" },
26
27
  "component": { "type": "string", "pattern": "^[A-Z][A-Za-z0-9]*$" },
27
- "props": { "type": "object", "description": "Optional JSON props passed to the component on its route. For a component that needs input to render anything." }
28
+ "props": { "type": "object", "description": "Optional JSON props passed to the component on its route. For a component that needs input to render anything." },
29
+ "icon": { "type": "string", "pattern": "^[A-Z][A-Za-z0-9]*$", "description": "Optional lucide-react export name (for example Users) shown beside the label in the sidebar." },
30
+ "group": { "type": "string", "minLength": 1, "description": "Optional sidebar section label. Entries with the same group sit together." },
31
+ "description": { "type": "string", "minLength": 1, "description": "Optional one line about the screen." },
32
+ "page": { "type": "string", "pattern": "^pages/[A-Za-z0-9_\\-/]+\\.tsx\\.tmpl$", "description": "Optional hand-written page template, relative to stacks/<stack-id>/. `create` writes it as the route's page.tsx instead of the generic route page; {{stackId}}, {{block}}, {{blockDir}}, {{component}}, {{importPath}} and {{propsJson}} are available." }
28
33
  }
29
34
  }
30
35
  }