@oxygen-agent/cli 1.982.3 → 1.1003.12

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 (127) hide show
  1. package/README.md +1 -1
  2. package/dist/admin-primary-providers-render.d.ts +0 -2
  3. package/dist/admin-primary-providers-render.js +1 -1
  4. package/dist/browser-login.js +1 -4
  5. package/dist/command-manifest.d.ts +3 -2
  6. package/dist/command-manifest.js +10 -0
  7. package/dist/credentials.d.ts +1 -1
  8. package/dist/functions-commands.js +27 -7
  9. package/dist/help.d.ts +29 -0
  10. package/dist/help.js +139 -0
  11. package/dist/index.js +1875 -164
  12. package/dist/knowledge-mirror.d.ts +2 -2
  13. package/dist/runtime.d.ts +0 -15
  14. package/dist/runtime.js +1 -1
  15. package/dist/session.d.ts +4 -3
  16. package/dist/skills.d.ts +8 -7
  17. package/dist/skills.js +24 -10
  18. package/dist/transcript.d.ts +2 -1
  19. package/dist/ugc-commands.d.ts +3 -6
  20. package/dist/ugc-commands.js +2 -1200
  21. package/dist/util.d.ts +1 -1
  22. package/dist/util.js +1 -3
  23. package/node_modules/@oxygen/cli-ugc/dist/commands.d.ts +3 -0
  24. package/node_modules/@oxygen/cli-ugc/dist/commands.js +1178 -0
  25. package/node_modules/@oxygen/cli-ugc/dist/field-parser.d.ts +7 -0
  26. package/node_modules/@oxygen/cli-ugc/dist/field-parser.js +25 -0
  27. package/node_modules/@oxygen/cli-ugc/dist/index.d.ts +14 -0
  28. package/node_modules/@oxygen/cli-ugc/dist/index.js +5 -0
  29. package/node_modules/@oxygen/cli-ugc/package.json +15 -0
  30. package/node_modules/@oxygen/formula/dist/coerce.d.ts +10 -0
  31. package/node_modules/@oxygen/formula/dist/coerce.js +10 -0
  32. package/node_modules/@oxygen/formula/dist/expression.js +14 -1
  33. package/node_modules/@oxygen/formula/dist/formula-functions.js +136 -1
  34. package/node_modules/@oxygen/formula/dist/hash.d.ts +19 -0
  35. package/node_modules/@oxygen/formula/dist/hash.js +199 -0
  36. package/node_modules/@oxygen/formula/dist/index.d.ts +1 -0
  37. package/node_modules/@oxygen/formula/dist/index.js +1 -0
  38. package/node_modules/@oxygen/formula/dist/value-cleaners.d.ts +74 -0
  39. package/node_modules/@oxygen/formula/dist/value-cleaners.js +358 -0
  40. package/node_modules/@oxygen/shared/dist/array-utils.d.ts +5 -0
  41. package/node_modules/@oxygen/shared/dist/array-utils.js +11 -0
  42. package/node_modules/@oxygen/shared/dist/billing.d.ts +103 -47
  43. package/node_modules/@oxygen/shared/dist/billing.js +150 -40
  44. package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +17 -0
  45. package/node_modules/@oxygen/shared/dist/capability-discovery.js +114 -16
  46. package/node_modules/@oxygen/shared/dist/column-autofill.d.ts +52 -0
  47. package/node_modules/@oxygen/shared/dist/column-autofill.js +80 -0
  48. package/node_modules/@oxygen/shared/dist/column-output-fields.js +14 -10
  49. package/node_modules/@oxygen/shared/dist/company-enrichment-fields.d.ts +108 -0
  50. package/node_modules/@oxygen/shared/dist/company-enrichment-fields.js +545 -0
  51. package/node_modules/@oxygen/shared/dist/copilot-playbooks.d.ts +18 -0
  52. package/node_modules/@oxygen/shared/dist/copilot-playbooks.js +43 -0
  53. package/node_modules/@oxygen/shared/dist/copilot-skills.d.ts +15 -0
  54. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.d.ts +31 -0
  55. package/node_modules/@oxygen/shared/dist/copilot-skills.generated.js +41 -0
  56. package/node_modules/@oxygen/shared/dist/copilot-skills.js +6 -0
  57. package/node_modules/@oxygen/shared/dist/deploy-env.d.ts +74 -0
  58. package/node_modules/@oxygen/shared/dist/deploy-env.js +82 -0
  59. package/node_modules/@oxygen/shared/dist/dnc-rules.d.ts +130 -0
  60. package/node_modules/@oxygen/shared/dist/dnc-rules.js +221 -0
  61. package/node_modules/@oxygen/shared/dist/enrichment-intents.d.ts +103 -0
  62. package/node_modules/@oxygen/shared/dist/enrichment-intents.js +819 -0
  63. package/node_modules/@oxygen/shared/dist/error-message.d.ts +1 -0
  64. package/node_modules/@oxygen/shared/dist/error-message.js +3 -0
  65. package/node_modules/@oxygen/shared/dist/error-redaction.js +1 -3
  66. package/node_modules/@oxygen/shared/dist/external-write-policy.d.ts +33 -0
  67. package/node_modules/@oxygen/shared/dist/external-write-policy.js +68 -0
  68. package/node_modules/@oxygen/shared/dist/format-percent.d.ts +8 -0
  69. package/node_modules/@oxygen/shared/dist/format-percent.js +13 -0
  70. package/node_modules/@oxygen/shared/dist/freemail-domains.d.ts +81 -0
  71. package/node_modules/@oxygen/shared/dist/freemail-domains.js +157 -0
  72. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.d.ts +1 -0
  73. package/node_modules/@oxygen/shared/dist/future-signup-lifecycle-projection.js +1 -1
  74. package/node_modules/@oxygen/shared/dist/index.d.ts +14 -0
  75. package/node_modules/@oxygen/shared/dist/index.js +14 -0
  76. package/node_modules/@oxygen/shared/dist/json-path.js +1 -3
  77. package/node_modules/@oxygen/shared/dist/knowledge-bases.js +1 -3
  78. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.d.ts +17 -2
  79. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.js +28 -6
  80. package/node_modules/@oxygen/shared/dist/langfuse.d.ts +12 -1
  81. package/node_modules/@oxygen/shared/dist/langfuse.js +57 -8
  82. package/node_modules/@oxygen/shared/dist/linkedin-countries.d.ts +32 -0
  83. package/node_modules/@oxygen/shared/dist/linkedin-countries.js +359 -0
  84. package/node_modules/@oxygen/shared/dist/log-sink-selector.d.ts +39 -0
  85. package/node_modules/@oxygen/shared/dist/log-sink-selector.js +56 -0
  86. package/node_modules/@oxygen/shared/dist/log.d.ts +1 -0
  87. package/node_modules/@oxygen/shared/dist/log.js +6 -1
  88. package/node_modules/@oxygen/shared/dist/object-storage.d.ts +17 -0
  89. package/node_modules/@oxygen/shared/dist/object-storage.js +21 -0
  90. package/node_modules/@oxygen/shared/dist/otlp-log-sink.d.ts +54 -0
  91. package/node_modules/@oxygen/shared/dist/otlp-log-sink.js +213 -0
  92. package/node_modules/@oxygen/shared/dist/plan-capabilities.js +1 -0
  93. package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +23 -22
  94. package/node_modules/@oxygen/shared/dist/plan-limits.js +45 -18
  95. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +48 -41
  96. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +36 -25
  97. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +22 -22
  98. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +40 -34
  99. package/node_modules/@oxygen/shared/dist/product-analytics-environment.js +9 -0
  100. package/node_modules/@oxygen/shared/dist/product-analytics-events.d.ts +15 -0
  101. package/node_modules/@oxygen/shared/dist/product-analytics-events.js +15 -0
  102. package/node_modules/@oxygen/shared/dist/rate-window.d.ts +5 -0
  103. package/node_modules/@oxygen/shared/dist/rate-window.js +8 -0
  104. package/node_modules/@oxygen/shared/dist/research-output-contract.d.ts +33 -1
  105. package/node_modules/@oxygen/shared/dist/research-output-contract.js +65 -5
  106. package/node_modules/@oxygen/shared/dist/search-vocab.js +4 -5
  107. package/node_modules/@oxygen/shared/dist/select-options.js +6 -1
  108. package/node_modules/@oxygen/shared/dist/sequence-crm-events.d.ts +1 -1
  109. package/node_modules/@oxygen/shared/dist/sequence-failures.js +1 -5
  110. package/node_modules/@oxygen/shared/dist/sequence-hubspot-sync.d.ts +1 -1
  111. package/node_modules/@oxygen/shared/dist/sequences.d.ts +49 -0
  112. package/node_modules/@oxygen/shared/dist/sequences.js +134 -4
  113. package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +22 -10
  114. package/node_modules/@oxygen/shared/dist/spend-safety.js +15 -21
  115. package/node_modules/@oxygen/shared/dist/sql-rows.d.ts +1 -0
  116. package/node_modules/@oxygen/shared/dist/sql-rows.js +3 -0
  117. package/node_modules/@oxygen/shared/dist/telemetry.js +9 -1
  118. package/node_modules/@oxygen/shared/dist/type-guards.d.ts +22 -0
  119. package/node_modules/@oxygen/shared/dist/type-guards.js +35 -0
  120. package/node_modules/@oxygen/shared/dist/value-readers.d.ts +21 -0
  121. package/node_modules/@oxygen/shared/dist/value-readers.js +59 -0
  122. package/node_modules/@oxygen/shared/dist/version.js +1 -1
  123. package/node_modules/@oxygen/shared/package.json +60 -0
  124. package/node_modules/@oxygen/workflows/dist/graph/expression.js +2 -5
  125. package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.d.ts +15 -15
  126. package/node_modules/@oxygen/workflows/dist/graph/params.js +1 -1
  127. package/package.json +6 -3
@@ -0,0 +1,545 @@
1
+ // The company-enrichment FIELD CATALOG: every field the company waterfall can
2
+ // resolve, with the vocabulary every surface shows for it.
3
+ //
4
+ // This is the single source of truth for the field list. The waterfall engine
5
+ // (packages/integrations/src/company-enrichment-waterfall.ts) owns HOW a field
6
+ // is resolved — provider lanes, derived extractors, pricing — and reads its
7
+ // labels, column keys and data types from here; the CLI, the MCP descriptor,
8
+ // the `company_enrich` column preset (tenant-db) and the web column picker
9
+ // read the same catalog, so a field cannot exist on one surface and not
10
+ // another. Three hand-copied 8-entry enums drifted independently before this
11
+ // module existed (route, MCP schema, engine), and only the engine's was tested.
12
+ //
13
+ // CLIENT-SAFE LEAF: exported as the `@oxygen/shared/company-enrichment-fields`
14
+ // subpath and imported by browser components through the tenant-db preset
15
+ // module. It must never gain a runtime import.
16
+ export const COMPANY_ENRICHMENT_FIELD_CATEGORIES = [
17
+ "identity",
18
+ "firmographics",
19
+ "funding",
20
+ "relationships",
21
+ "signals",
22
+ "technology",
23
+ "web_presence",
24
+ ];
25
+ export const COMPANY_ENRICHMENT_FIELD_CATEGORY_LABELS = {
26
+ identity: "Identity",
27
+ firmographics: "Firmographics",
28
+ funding: "Funding",
29
+ relationships: "Relationships",
30
+ signals: "Signals",
31
+ technology: "Technology",
32
+ web_presence: "Web presence",
33
+ };
34
+ const PROFILE_THEN_FUNDING = [
35
+ { field: "company_profile", autoRun: true },
36
+ { field: "funding", autoRun: false },
37
+ ];
38
+ export const COMPANY_ENRICHMENT_FIELD_DEFINITIONS = [
39
+ // ── identity ─────────────────────────────────────────────────────────────
40
+ {
41
+ field: "domain",
42
+ label: "Company domain",
43
+ category: "identity",
44
+ description: "The company's website domain, resolved from its name or LinkedIn page.",
45
+ columnKey: "company_domain",
46
+ dataType: "text",
47
+ semanticType: "company.domain",
48
+ derivedFrom: [],
49
+ },
50
+ {
51
+ field: "linkedin_url",
52
+ label: "Company LinkedIn URL",
53
+ category: "identity",
54
+ description: "The company's LinkedIn page, resolved from its domain or name.",
55
+ columnKey: "company_linkedin_url",
56
+ dataType: "text",
57
+ semanticType: "company.linkedin_url",
58
+ derivedFrom: [],
59
+ },
60
+ // ── firmographics ────────────────────────────────────────────────────────
61
+ {
62
+ field: "headcount",
63
+ label: "Headcount",
64
+ category: "firmographics",
65
+ description: "Employee count, exact when the provider has it, otherwise the size band.",
66
+ columnKey: "company_headcount",
67
+ dataType: "text",
68
+ semanticType: "company.employee_count",
69
+ derivedFrom: [],
70
+ },
71
+ {
72
+ field: "industry",
73
+ label: "Industry",
74
+ category: "firmographics",
75
+ description: "The industry the company lists for itself.",
76
+ columnKey: "company_industry",
77
+ dataType: "text",
78
+ semanticType: "company.industry",
79
+ derivedFrom: [],
80
+ },
81
+ {
82
+ field: "company_profile",
83
+ label: "Company profile",
84
+ category: "firmographics",
85
+ description: "The whole provider profile as one record; the free fields below are read out of it.",
86
+ columnKey: "company_profile",
87
+ dataType: "jsonb",
88
+ semanticType: null,
89
+ derivedFrom: [],
90
+ },
91
+ {
92
+ field: "description",
93
+ label: "Description",
94
+ category: "firmographics",
95
+ description: "The company's own about text, read from the profile already fetched.",
96
+ columnKey: "company_description",
97
+ dataType: "text",
98
+ semanticType: "company.description",
99
+ derivedFrom: PROFILE_THEN_FUNDING,
100
+ },
101
+ {
102
+ field: "founded_year",
103
+ label: "Founded year",
104
+ category: "firmographics",
105
+ description: "The year the company was founded, read from the profile already fetched.",
106
+ columnKey: "company_founded_year",
107
+ dataType: "numeric",
108
+ semanticType: "company.founded_year",
109
+ derivedFrom: PROFILE_THEN_FUNDING,
110
+ },
111
+ {
112
+ field: "hq_address",
113
+ label: "HQ address",
114
+ category: "firmographics",
115
+ description: "Headquarters street, city and country as one line, from the profile already fetched.",
116
+ columnKey: "company_hq_address",
117
+ dataType: "text",
118
+ semanticType: "company.hq_location",
119
+ derivedFrom: PROFILE_THEN_FUNDING,
120
+ },
121
+ {
122
+ field: "hq_country",
123
+ label: "HQ country",
124
+ category: "firmographics",
125
+ description: "Headquarters country, from the profile already fetched.",
126
+ columnKey: "company_hq_country",
127
+ dataType: "text",
128
+ semanticType: "company.hq_country",
129
+ derivedFrom: PROFILE_THEN_FUNDING,
130
+ },
131
+ {
132
+ field: "company_type",
133
+ label: "Company type",
134
+ category: "firmographics",
135
+ description: "Privately held, public, non-profit and the like, from the profile already fetched.",
136
+ columnKey: "company_type",
137
+ dataType: "text",
138
+ semanticType: null,
139
+ derivedFrom: PROFILE_THEN_FUNDING,
140
+ },
141
+ {
142
+ field: "specialties",
143
+ label: "Specialties",
144
+ category: "firmographics",
145
+ description: "The specialties or keywords the company lists, from the profile already fetched.",
146
+ columnKey: "company_specialties",
147
+ dataType: "jsonb",
148
+ semanticType: "company.specialties",
149
+ derivedFrom: [{ field: "company_profile", autoRun: true }],
150
+ },
151
+ // ── funding ──────────────────────────────────────────────────────────────
152
+ {
153
+ field: "funding",
154
+ label: "Funding",
155
+ category: "funding",
156
+ description: "The raw funding record from a funding provider: rounds, amounts, investors, total.",
157
+ columnKey: "company_funding",
158
+ dataType: "jsonb",
159
+ semanticType: null,
160
+ derivedFrom: [],
161
+ },
162
+ {
163
+ field: "revenue",
164
+ label: "Revenue (estimate)",
165
+ category: "funding",
166
+ description: "Estimated annual revenue, a figure when the source has one, otherwise a range band.",
167
+ columnKey: "company_revenue",
168
+ dataType: "text",
169
+ semanticType: "company.revenue",
170
+ derivedFrom: [],
171
+ },
172
+ {
173
+ field: "funding_stage",
174
+ label: "Funding stage",
175
+ category: "funding",
176
+ description: "The latest round's type, e.g. Seed or Series B; free when the LinkedIn page lists funding.",
177
+ columnKey: "company_funding_stage",
178
+ dataType: "text",
179
+ semanticType: null,
180
+ derivedFrom: PROFILE_THEN_FUNDING,
181
+ },
182
+ {
183
+ field: "latest_funding_round",
184
+ label: "Latest funding round",
185
+ category: "funding",
186
+ description: "Date, amount, round type and lead investors of the most recent round.",
187
+ columnKey: "company_latest_funding_round",
188
+ dataType: "jsonb",
189
+ semanticType: null,
190
+ derivedFrom: PROFILE_THEN_FUNDING,
191
+ },
192
+ {
193
+ field: "total_funding",
194
+ label: "Total funding",
195
+ category: "funding",
196
+ description: "Total raised to date in USD, from a funding provider (LinkedIn does not publish it).",
197
+ columnKey: "company_total_funding",
198
+ dataType: "numeric",
199
+ semanticType: "company.funding_raised",
200
+ derivedFrom: [
201
+ { field: "funding", autoRun: true },
202
+ { field: "company_profile", autoRun: false },
203
+ ],
204
+ },
205
+ {
206
+ field: "funding_rounds_count",
207
+ label: "Number of funding rounds",
208
+ category: "funding",
209
+ description: "How many rounds the company has raised.",
210
+ columnKey: "company_funding_rounds_count",
211
+ dataType: "numeric",
212
+ semanticType: null,
213
+ derivedFrom: PROFILE_THEN_FUNDING,
214
+ },
215
+ {
216
+ field: "investors",
217
+ label: "Investors",
218
+ category: "funding",
219
+ description: "Named investors across the rounds a provider knows about.",
220
+ columnKey: "company_investors",
221
+ dataType: "jsonb",
222
+ semanticType: null,
223
+ derivedFrom: PROFILE_THEN_FUNDING,
224
+ },
225
+ // ── relationships ────────────────────────────────────────────────────────
226
+ {
227
+ field: "competitors",
228
+ label: "Competitors",
229
+ category: "relationships",
230
+ description: "Named competitors from a funding-intelligence provider; LinkedIn's similar pages when the profile is already on the row.",
231
+ columnKey: "company_competitors",
232
+ dataType: "jsonb",
233
+ semanticType: null,
234
+ derivedFrom: [
235
+ { field: "funding", autoRun: false },
236
+ { field: "company_profile", autoRun: false },
237
+ ],
238
+ availability: "coming_soon",
239
+ },
240
+ {
241
+ field: "corporate_structure",
242
+ label: "Corporate structure",
243
+ category: "relationships",
244
+ description: "Parent company and subsidiaries as one record.",
245
+ columnKey: "company_corporate_structure",
246
+ dataType: "jsonb",
247
+ semanticType: null,
248
+ derivedFrom: [],
249
+ availability: "coming_soon",
250
+ },
251
+ {
252
+ field: "parent_company",
253
+ label: "Parent company",
254
+ category: "relationships",
255
+ description: "The company that owns this one, read from the corporate structure lookup.",
256
+ columnKey: "company_parent_company",
257
+ dataType: "text",
258
+ semanticType: null,
259
+ derivedFrom: [{ field: "corporate_structure", autoRun: true }],
260
+ availability: "coming_soon",
261
+ },
262
+ {
263
+ field: "subsidiaries",
264
+ label: "Subsidiaries",
265
+ category: "relationships",
266
+ description: "Companies this one owns, read from the corporate structure lookup.",
267
+ columnKey: "company_subsidiaries",
268
+ dataType: "jsonb",
269
+ semanticType: null,
270
+ derivedFrom: [{ field: "corporate_structure", autoRun: true }],
271
+ availability: "coming_soon",
272
+ },
273
+ {
274
+ field: "acquisitions",
275
+ label: "Acquisitions",
276
+ category: "relationships",
277
+ description: "Companies this one has acquired, with dates and sources.",
278
+ columnKey: "company_acquisitions",
279
+ dataType: "jsonb",
280
+ semanticType: null,
281
+ derivedFrom: [{ field: "funding", autoRun: false }],
282
+ availability: "coming_soon",
283
+ },
284
+ // ── signals ──────────────────────────────────────────────────────────────
285
+ {
286
+ field: "news",
287
+ label: "News",
288
+ category: "signals",
289
+ description: "Recent dated news items about the company.",
290
+ columnKey: "company_news",
291
+ dataType: "jsonb",
292
+ semanticType: null,
293
+ derivedFrom: [{ field: "funding", autoRun: false }],
294
+ availability: "coming_soon",
295
+ },
296
+ {
297
+ field: "hiring_signals",
298
+ label: "Hiring signals",
299
+ category: "signals",
300
+ description: "The raw open-roles payload from a jobs provider.",
301
+ columnKey: "company_hiring_signals",
302
+ dataType: "jsonb",
303
+ semanticType: null,
304
+ derivedFrom: [],
305
+ },
306
+ {
307
+ field: "job_openings",
308
+ label: "Job openings",
309
+ category: "signals",
310
+ description: "Open roles from the hiring lookup, listed (up to ten) with a count.",
311
+ columnKey: "company_job_openings",
312
+ dataType: "jsonb",
313
+ semanticType: null,
314
+ derivedFrom: [{ field: "hiring_signals", autoRun: true }],
315
+ },
316
+ // ── technology ───────────────────────────────────────────────────────────
317
+ {
318
+ field: "technologies",
319
+ label: "Tech stack",
320
+ category: "technology",
321
+ description: "Technologies the company runs, from its job postings (with confidence and first/last-seen dates) or its website.",
322
+ columnKey: "company_technologies",
323
+ dataType: "jsonb",
324
+ semanticType: null,
325
+ derivedFrom: [],
326
+ },
327
+ {
328
+ field: "technology_check",
329
+ label: "Technology check",
330
+ category: "technology",
331
+ description: "Yes or no per technology you name, checked against the detected stack.",
332
+ columnKey: "company_technology_check",
333
+ dataType: "jsonb",
334
+ semanticType: null,
335
+ derivedFrom: [{ field: "technologies", autoRun: true }],
336
+ requires: "check_technologies",
337
+ },
338
+ // ── web presence ─────────────────────────────────────────────────────────
339
+ {
340
+ field: "logo_url",
341
+ label: "Logo",
342
+ category: "web_presence",
343
+ description: "The company logo image URL, from the profile already fetched.",
344
+ columnKey: "company_logo_url",
345
+ dataType: "text",
346
+ semanticType: "company.logo_url",
347
+ derivedFrom: [{ field: "company_profile", autoRun: true }],
348
+ },
349
+ {
350
+ field: "crunchbase_url",
351
+ label: "Crunchbase URL",
352
+ category: "web_presence",
353
+ description: "The company's Crunchbase page; free when the LinkedIn page links it, otherwise one web search.",
354
+ columnKey: "company_crunchbase_url",
355
+ dataType: "text",
356
+ semanticType: null,
357
+ derivedFrom: [
358
+ { field: "company_profile", autoRun: false },
359
+ { field: "funding", autoRun: false },
360
+ ],
361
+ availability: "coming_soon",
362
+ },
363
+ {
364
+ field: "github_url",
365
+ label: "GitHub URL",
366
+ category: "web_presence",
367
+ description: "The company's GitHub organization, found by one site-scoped web search.",
368
+ columnKey: "company_github_url",
369
+ dataType: "text",
370
+ semanticType: null,
371
+ derivedFrom: [],
372
+ availability: "coming_soon",
373
+ },
374
+ {
375
+ field: "facebook_url",
376
+ label: "Facebook URL",
377
+ category: "web_presence",
378
+ description: "The company's Facebook page, found by one site-scoped web search.",
379
+ columnKey: "company_facebook_url",
380
+ dataType: "text",
381
+ semanticType: "company.facebook_url",
382
+ derivedFrom: [{ field: "funding", autoRun: false }],
383
+ availability: "coming_soon",
384
+ },
385
+ {
386
+ field: "instagram_url",
387
+ label: "Instagram URL",
388
+ category: "web_presence",
389
+ description: "The company's Instagram profile, found by one site-scoped web search.",
390
+ columnKey: "company_instagram_url",
391
+ dataType: "text",
392
+ semanticType: "company.instagram_url",
393
+ derivedFrom: [],
394
+ availability: "coming_soon",
395
+ },
396
+ {
397
+ field: "youtube_url",
398
+ label: "YouTube URL",
399
+ category: "web_presence",
400
+ description: "The company's YouTube channel, found by one site-scoped web search.",
401
+ columnKey: "company_youtube_url",
402
+ dataType: "text",
403
+ semanticType: null,
404
+ derivedFrom: [],
405
+ availability: "coming_soon",
406
+ },
407
+ ];
408
+ export const COMPANY_ENRICHMENT_FIELD_KEYS = COMPANY_ENRICHMENT_FIELD_DEFINITIONS.map((definition) => definition.field);
409
+ const DEFINITIONS_BY_FIELD = new Map(COMPANY_ENRICHMENT_FIELD_DEFINITIONS.map((definition) => [definition.field, definition]));
410
+ export function isCompanyEnrichmentFieldKey(value) {
411
+ return DEFINITIONS_BY_FIELD.has(value);
412
+ }
413
+ export function companyEnrichmentFieldDefinition(field) {
414
+ const definition = DEFINITIONS_BY_FIELD.get(field);
415
+ if (!definition)
416
+ throw new Error(`Unknown company enrichment field "${field}".`);
417
+ return definition;
418
+ }
419
+ /** D51: a field parked `coming_soon` has no lane, no picker group and is refused by `--fields`. */
420
+ export function isComingSoonCompanyEnrichmentField(field) {
421
+ return companyEnrichmentFieldDefinition(field).availability === "coming_soon";
422
+ }
423
+ /** A field whose value is read out of another field's payload, never a provider call of its own. */
424
+ export function isDerivedCompanyEnrichmentField(field) {
425
+ return companyEnrichmentFieldDefinition(field).derivedFrom.length > 0;
426
+ }
427
+ /**
428
+ * What `find company` resolves when the caller names no fields. Identity plus
429
+ * the firmographics that cost nothing beyond the one profile lookup the
430
+ * headcount/industry lanes already make; funding, relationship and web-presence
431
+ * fields stay opt-in because each adds a priced lane.
432
+ */
433
+ export const DEFAULT_COMPANY_FIND_FIELDS = [
434
+ "domain",
435
+ "linkedin_url",
436
+ "headcount",
437
+ "industry",
438
+ "description",
439
+ "founded_year",
440
+ "hq_country",
441
+ ];
442
+ /**
443
+ * What `columns add --preset company_enrich` creates when the caller names no
444
+ * fields: the identity/firmographic set plus the full profile and the funding
445
+ * facts LinkedIn publishes for free off that same profile. Every lane-priced
446
+ * relationship, signal, technology and web-presence field is opt-in through
447
+ * `--fields`, so the default bundle's per-row ceiling stays the profile chain's.
448
+ */
449
+ export const DEFAULT_COMPANY_PRESET_FIELDS = [
450
+ "domain",
451
+ "linkedin_url",
452
+ "headcount",
453
+ "industry",
454
+ "company_profile",
455
+ "description",
456
+ "founded_year",
457
+ "hq_country",
458
+ "funding_stage",
459
+ "latest_funding_round",
460
+ ];
461
+ /**
462
+ * The opt-in company fields, grouped the way a customer asks for them ("add
463
+ * competitors", "add their tech stack"). Every surface that offers a company
464
+ * field beyond the default bundle reads THIS list: the enrichment column catalog
465
+ * (`oxygen enrichment catalog`, `oxygen_enrichment_catalog`), the web add-column
466
+ * picker, and the catalog pricing. Adding a group adds its fields to the SAME
467
+ * company enrichment column — re-applying the bundle widens the existing
468
+ * column's field list instead of creating a second paid column.
469
+ */
470
+ export const COMPANY_ENRICHMENT_FIELD_GROUPS = [
471
+ {
472
+ id: "profile_details",
473
+ label: "Company profile details",
474
+ description: "HQ address, company type, specialties and logo, read from the company profile the bundle already fetches.",
475
+ fields: ["hq_address", "company_type", "specialties", "logo_url"],
476
+ cost: "included",
477
+ },
478
+ {
479
+ id: "funding_details",
480
+ label: "Funding details",
481
+ description: "Total raised, number of rounds and investors, with the full funding history kept alongside.",
482
+ fields: ["funding", "revenue", "total_funding", "funding_rounds_count", "investors"],
483
+ cost: "extra",
484
+ },
485
+ {
486
+ id: "job_openings",
487
+ label: "Job openings",
488
+ description: "The roles each account is hiring for, as a count and a list.",
489
+ fields: ["hiring_signals", "job_openings"],
490
+ cost: "extra",
491
+ },
492
+ {
493
+ id: "tech_stack",
494
+ label: "Tech stack",
495
+ description: "The technologies each account runs, from its job postings (with confidence and first/last seen) or its website.",
496
+ fields: ["technologies"],
497
+ cost: "extra",
498
+ },
499
+ {
500
+ id: "technology_check",
501
+ label: "Technology check",
502
+ description: "Yes or no per account for each technology you name, such as HubSpot or Salesforce.",
503
+ fields: ["technology_check"],
504
+ cost: "extra",
505
+ requires: "check_technologies",
506
+ },
507
+ ];
508
+ export function companyEnrichmentFieldGroup(id) {
509
+ return COMPANY_ENRICHMENT_FIELD_GROUPS.find((group) => group.id === id) ?? null;
510
+ }
511
+ /**
512
+ * Parse a comma-separated or array field list against the catalog. Returns the
513
+ * unique, lowercased keys in request order, or throws naming every unknown
514
+ * entry with the supported list — never a silent fallback to a default set,
515
+ * which is how `--fields tech,hiring,profile` once ran the four default fields
516
+ * and billed for an answer nobody asked for (OXP-7.2.9).
517
+ */
518
+ export function parseCompanyEnrichmentFieldList(value) {
519
+ const entries = Array.isArray(value)
520
+ ? value
521
+ : typeof value === "string"
522
+ ? value.split(",")
523
+ : [];
524
+ const cleaned = entries
525
+ .map((entry) => (typeof entry === "string" ? entry.trim().toLowerCase() : ""))
526
+ .filter((entry) => entry.length > 0);
527
+ const fields = [];
528
+ const unknown = [];
529
+ const coming_soon = [];
530
+ for (const entry of cleaned) {
531
+ if (isCompanyEnrichmentFieldKey(entry)) {
532
+ if (isComingSoonCompanyEnrichmentField(entry)) {
533
+ if (!coming_soon.includes(entry))
534
+ coming_soon.push(entry);
535
+ }
536
+ else if (!fields.includes(entry)) {
537
+ fields.push(entry);
538
+ }
539
+ }
540
+ else if (!unknown.includes(entry)) {
541
+ unknown.push(entry);
542
+ }
543
+ }
544
+ return { fields, unknown, coming_soon };
545
+ }
@@ -0,0 +1,18 @@
1
+ export type CopilotPlaybookSlug = "tam-sourcing" | "linkedin-content-strategy" | "inbound-led-outbound" | "signal-based-outbound";
2
+ export type CopilotPlaybook = {
3
+ /**
4
+ * The skill slug the Copilot loads through its `skills` tool, and the
5
+ * `name:` in the playbook file's frontmatter. The two are gated equal.
6
+ */
7
+ slug: CopilotPlaybookSlug;
8
+ /** Customer-facing name, exactly as it is spoken in the composer prompt and shown on the Home chip. */
9
+ title: string;
10
+ };
11
+ export declare const COPILOT_PLAYBOOKS: readonly CopilotPlaybook[];
12
+ /**
13
+ * The sentence a Home card writes into the composer. It names the skill the way
14
+ * a person would say it, and the Copilot's prompt maps that title back to the
15
+ * slug — so the user reads and sends exactly what the card promised.
16
+ */
17
+ export declare function copilotPlaybookPrompt(playbook: Pick<CopilotPlaybook, "title">): string;
18
+ export declare function getCopilotPlaybook(slug: string): CopilotPlaybook | null;
@@ -0,0 +1,43 @@
1
+ // The four end-to-end GTM playbooks the Workspace Copilot can run, as pure,
2
+ // client-safe data. One canonical copy is read by three consumers: the Home
3
+ // cards (which pre-write the prompt below into the composer), the Copilot's
4
+ // system prompt (which maps the spoken title back to the skill slug the model
5
+ // loads through its `skills` tool), and the apps/web gate that checks every slug
6
+ // here has a served playbook file with a matching frontmatter `name`.
7
+ //
8
+ // A playbook is the operator contract for one whole motion — stages, owners,
9
+ // exact commands, caps, approval gates, stop conditions, learning loop — served
10
+ // as a product skill (`apps/web/src/agent-skills/oxygen-playbooks/playbooks/`).
11
+ // Loading one is never permission to spend or send: every gate inside it still
12
+ // fires. Founder decision 2026-09-16: Home offers exactly these four, above the
13
+ // composer as compact glass chips (title only), and a chip writes the sentence
14
+ // into the box rather than starting a session, so there stays exactly one door.
15
+ export const COPILOT_PLAYBOOKS = [
16
+ {
17
+ slug: "tam-sourcing",
18
+ title: "TAM sourcing",
19
+ },
20
+ {
21
+ slug: "linkedin-content-strategy",
22
+ title: "LinkedIn content strategy",
23
+ },
24
+ {
25
+ slug: "inbound-led-outbound",
26
+ title: "Inbound-led outbound",
27
+ },
28
+ {
29
+ slug: "signal-based-outbound",
30
+ title: "Signal-based outbound",
31
+ },
32
+ ];
33
+ /**
34
+ * The sentence a Home card writes into the composer. It names the skill the way
35
+ * a person would say it, and the Copilot's prompt maps that title back to the
36
+ * slug — so the user reads and sends exactly what the card promised.
37
+ */
38
+ export function copilotPlaybookPrompt(playbook) {
39
+ return `Use the ${playbook.title} skill to get started.`;
40
+ }
41
+ export function getCopilotPlaybook(slug) {
42
+ return COPILOT_PLAYBOOKS.find((playbook) => playbook.slug === slug) ?? null;
43
+ }
@@ -0,0 +1,15 @@
1
+ export type CopilotSkillSnapshot = {
2
+ /** What the model passes to the `skills` tool; equals the bundle's frontmatter `name`. */
3
+ slug: string;
4
+ /** Catalog title, shown when the frontmatter carries no description. */
5
+ title: string;
6
+ /** Served skill files bundled into `content`, as `skill/path`, for provenance. */
7
+ sources: readonly string[];
8
+ /** The exact bundle the tool serves, frontmatter included. */
9
+ content: string;
10
+ /** Lowercase hex sha256 of `content`; the runtime re-hashes every served body against it. */
11
+ sha256: string;
12
+ };
13
+ export declare const COPILOT_SKILL_SNAPSHOTS: readonly CopilotSkillSnapshot[];
14
+ export declare const COPILOT_SKILL_SLUGS: readonly string[];
15
+ export declare function getCopilotSkillSnapshot(slug: string): CopilotSkillSnapshot | null;