@oxygen-agent/cli 1.591.1 → 1.610.7
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/README.md +1 -1
- package/dist/command-manifest.d.ts +18 -0
- package/dist/command-manifest.js +106 -5
- package/dist/help.js +2 -1
- package/dist/index.js +273 -38
- package/dist/skills.d.ts +6 -0
- package/dist/skills.js +200 -1
- package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +36 -0
- package/node_modules/@oxygen/shared/dist/capability-discovery.js +766 -0
- package/node_modules/@oxygen/shared/dist/cli-result.js +4 -3
- package/node_modules/@oxygen/shared/dist/index.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/index.js +2 -0
- package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/pricing-sheet.js +1 -1
- package/node_modules/@oxygen/shared/dist/recipes.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/recipes.js +4 -2
- package/node_modules/@oxygen/shared/dist/sequence-template.js +0 -0
- package/node_modules/@oxygen/shared/dist/sequence-terminal-events.d.ts +47 -0
- package/node_modules/@oxygen/shared/dist/sequence-terminal-events.js +70 -0
- package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.js +1 -1
- package/node_modules/@oxygen/workflows/dist/graph/lint.js +3 -0
- package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.d.ts +5 -0
- package/node_modules/@oxygen/workflows/dist/graph/manifest-schema.js +5 -0
- package/node_modules/@oxygen/workflows/dist/graph/types.d.ts +2 -0
- package/node_modules/@oxygen/workflows/dist/index.d.ts +4 -0
- package/node_modules/@oxygen/workflows/dist/index.js +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,766 @@
|
|
|
1
|
+
import { RECIPE_PRIMITIVES } from "./recipes.js";
|
|
2
|
+
// One compact semantic index covers every top-level /api/cli endpoint section.
|
|
3
|
+
// It is navigation, never execution: live schemas, prices, readiness, and
|
|
4
|
+
// approval enforcement remain on the exact command/tool selected from here.
|
|
5
|
+
export const OXYGEN_CAPABILITY_ROUTES = [
|
|
6
|
+
{
|
|
7
|
+
id: "workspace-access",
|
|
8
|
+
layer: "Control",
|
|
9
|
+
primitive: null,
|
|
10
|
+
owns: "Authentication, CLI identities, API keys, sessions, organizations, and active-workspace selection.",
|
|
11
|
+
notFor: "Workspace GTM data, provider credentials, or execution inside a primitive.",
|
|
12
|
+
execution: "Resolve identity and select the hosted workspace before operating its primitives.",
|
|
13
|
+
posture: "mixed",
|
|
14
|
+
gatewayTools: ["oxygen_whoami", "oxygen_orgs_list", "oxygen_orgs_select"],
|
|
15
|
+
gatewayCommands: ["whoami", "orgs list", "orgs select"],
|
|
16
|
+
skills: ["oxygen-quickstart"],
|
|
17
|
+
endpointSections: ["api-keys", "auth", "login-requests", "orgs", "sessions", "settings", "whoami"],
|
|
18
|
+
intentTerms: ["login", "authenticate", "identity", "who am i", "workspace", "organization", "org", "api key", "session", "switch workspace"],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "discovery-and-skills",
|
|
22
|
+
layer: "Control",
|
|
23
|
+
primitive: null,
|
|
24
|
+
owns: "Bounded capability, command, provider-operation, Recipe, and product-skill discovery with exact hydration on demand.",
|
|
25
|
+
notFor: "Executing GTM work or loading full manifests and schemas before a capability is selected.",
|
|
26
|
+
execution: "Search by outcome, choose the owner, then hydrate one exact command, MCP schema, provider descriptor, or skill.",
|
|
27
|
+
posture: "read_only",
|
|
28
|
+
gatewayTools: ["oxygen_capabilities_search", "oxygen_tools_search", "oxygen_recipes_list"],
|
|
29
|
+
gatewayCommands: ["capabilities search", "commands search", "skills search", "tools search", "recipes list"],
|
|
30
|
+
skills: ["oxygen-quickstart", "oxygen-gtm"],
|
|
31
|
+
endpointSections: ["skills"],
|
|
32
|
+
intentTerms: ["discover", "discovery", "capability", "capabilities", "command", "commands", "skill", "skills", "which tool", "how do i"],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "onboarding-and-copilot",
|
|
36
|
+
layer: "Control",
|
|
37
|
+
primitive: null,
|
|
38
|
+
owns: "First-run setup and interactive Workspace Copilot sessions over the shared primitive contracts.",
|
|
39
|
+
notFor: "Recurring deterministic automation or standing adaptive jobs; use Workflows or Agents.",
|
|
40
|
+
execution: "Start onboarding or a hosted Copilot session; every resulting action still uses its native primitive gate.",
|
|
41
|
+
posture: "mixed",
|
|
42
|
+
gatewayTools: ["oxygen_whoami", "oxygen_context_resolve", "oxygen_copilot_start"],
|
|
43
|
+
gatewayCommands: ["whoami", "context resolve", "copilot start"],
|
|
44
|
+
skills: ["oxygen-quickstart", "oxygen-gtm"],
|
|
45
|
+
endpointSections: ["copilot", "home"],
|
|
46
|
+
intentTerms: ["onboard", "onboarding", "first run", "first day", "setup oxygen", "copilot", "assistant", "guided"],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "billing-and-budgets",
|
|
50
|
+
layer: "Control",
|
|
51
|
+
primitive: null,
|
|
52
|
+
owns: "Credits, plan state, usage receipts, subscriptions, and standing budget policies.",
|
|
53
|
+
notFor: "Authorizing a specific provider call or external write; that action still needs its own preview and approval.",
|
|
54
|
+
execution: "Read billing state or set a hosted budget policy; exact action ceilings remain primitive-owned.",
|
|
55
|
+
posture: "mixed",
|
|
56
|
+
gatewayTools: ["oxygen_billing_balance", "oxygen_billing_usage", "oxygen_budget_list"],
|
|
57
|
+
gatewayCommands: ["billing balance", "billing usage", "budget list"],
|
|
58
|
+
skills: ["oxygen-gtm", "oxygen-diagnostics"],
|
|
59
|
+
endpointSections: ["billing", "budget", "limits"],
|
|
60
|
+
intentTerms: ["billing", "credits", "credit balance", "usage", "spend", "cost", "budget", "subscription", "invoice", "cancel plan"],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: "support-and-feedback",
|
|
64
|
+
layer: "Control",
|
|
65
|
+
primitive: null,
|
|
66
|
+
owns: "Customer support tickets, product feedback, transcript-backed reports, and ticket follow-up.",
|
|
67
|
+
notFor: "Primitive run diagnosis when no support report is needed; inspect Observability first.",
|
|
68
|
+
execution: "File or inspect a hosted support record and return its deep link; never send a customer reply automatically.",
|
|
69
|
+
posture: "workspace_write",
|
|
70
|
+
gatewayTools: ["oxygen_feedback", "oxygen_support_ticket_create", "oxygen_support_tickets_list"],
|
|
71
|
+
gatewayCommands: ["feedback", "support file", "support list"],
|
|
72
|
+
skills: ["oxygen-feedback"],
|
|
73
|
+
endpointSections: ["feedback", "support"],
|
|
74
|
+
intentTerms: ["support", "feedback", "bug report", "feature request", "report issue", "ticket", "complaint"],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: "platform-operations",
|
|
78
|
+
layer: "Control",
|
|
79
|
+
primitive: null,
|
|
80
|
+
owns: "Staff/admin diagnostics, worker queue health, tenant repair, and database operating surfaces.",
|
|
81
|
+
notFor: "Ordinary customer GTM work or product Observability over customer-visible runs.",
|
|
82
|
+
execution: "Use the authenticated hosted operational endpoints; production mutations and migrations keep their human gates.",
|
|
83
|
+
posture: "mixed",
|
|
84
|
+
gatewayTools: ["oxygen_worker_queue_stats", "oxygen_worker_failures", "oxygen_observability_runs"],
|
|
85
|
+
gatewayCommands: ["worker queue-stats", "worker failures", "db status"],
|
|
86
|
+
skills: ["oxygen-diagnostics"],
|
|
87
|
+
endpointSections: ["admin", "db", "worker"],
|
|
88
|
+
intentTerms: ["admin", "worker", "queue", "tenant repair", "database", "db status", "stuck jobs", "operations"],
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: "agency-directory",
|
|
92
|
+
layer: "Control",
|
|
93
|
+
primitive: null,
|
|
94
|
+
owns: "The current organization profile and publication state in the public OXYGEN agency directory.",
|
|
95
|
+
notFor: "CRM company records, workspace membership, or outbound campaigns.",
|
|
96
|
+
execution: "Read, update, publish, or unpublish the hosted directory listing.",
|
|
97
|
+
posture: "workspace_write",
|
|
98
|
+
gatewayTools: ["oxygen_directory_get", "oxygen_directory_update", "oxygen_directory_publish"],
|
|
99
|
+
gatewayCommands: ["directory get", "directory update", "directory publish"],
|
|
100
|
+
skills: ["oxygen-agency-directory"],
|
|
101
|
+
endpointSections: ["directory"],
|
|
102
|
+
intentTerms: ["agency directory", "agency listing", "directory profile", "publish agency", "partner listing"],
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: "knowledge-graph",
|
|
106
|
+
layer: "Knowledge",
|
|
107
|
+
primitive: "knowledge-graph",
|
|
108
|
+
owns: "Durable workspace context: company, ICP, positioning, offers, rubrics, prompts, and linked wiki pages.",
|
|
109
|
+
notFor: "Working row sets, campaign execution, or local chat memory.",
|
|
110
|
+
execution: "Read and write the hosted workspace Knowledge Graph; canonical changes remain proposal-gated.",
|
|
111
|
+
posture: "workspace_write",
|
|
112
|
+
gatewayTools: ["oxygen_knowledge_search", "oxygen_knowledge_index", "oxygen_knowledge_page_get"],
|
|
113
|
+
gatewayCommands: ["knowledge search", "knowledge index", "knowledge page get"],
|
|
114
|
+
skills: ["oxygen-knowledge"],
|
|
115
|
+
endpointSections: ["context", "knowledge"],
|
|
116
|
+
intentTerms: ["knowledge", "wiki", "context", "icp", "positioning", "offer", "rubric", "brand", "voice", "company profile"],
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: "recipes",
|
|
120
|
+
layer: "Knowledge",
|
|
121
|
+
primitive: "recipes",
|
|
122
|
+
owns: "Versioned advisory playbooks that teach when and why to run proven GTM motions through native primitives.",
|
|
123
|
+
notFor: "A hidden runtime, mandatory bundle, or replacement for hosted Workflows.",
|
|
124
|
+
execution: "Browse or install the Recipe; optional Blueprints scaffold infrastructure while native primitives execute.",
|
|
125
|
+
posture: "workspace_write",
|
|
126
|
+
gatewayTools: ["oxygen_recipes_list", "oxygen_recipes_get"],
|
|
127
|
+
gatewayCommands: ["recipes list", "recipes show", "recipes install"],
|
|
128
|
+
skills: ["oxygen-recipes"],
|
|
129
|
+
endpointSections: ["blueprints", "recipes", "templates"],
|
|
130
|
+
intentTerms: ["recipe", "playbook", "proven play", "journey", "day 1", "day 7", "day 30", "blueprint", "template", "what should i do"],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: "records",
|
|
134
|
+
layer: "Data",
|
|
135
|
+
primitive: "records",
|
|
136
|
+
owns: "Canonical companies, people, deals, identities, relationships, activities, merges, and CRM sync state.",
|
|
137
|
+
notFor: "Disposable sourcing, enrichment, or scoring work; use Tables before promotion.",
|
|
138
|
+
execution: "Operate the hosted native CRM and preserve field/relationship provenance.",
|
|
139
|
+
posture: "workspace_write",
|
|
140
|
+
gatewayTools: ["oxygen_crm_record_search", "oxygen_crm_record_get"],
|
|
141
|
+
gatewayCommands: ["crm search", "crm get", "crm describe"],
|
|
142
|
+
skills: ["oxygen-gtm"],
|
|
143
|
+
endpointSections: ["crm"],
|
|
144
|
+
intentTerms: ["record", "records", "crm", "company record", "contact", "person record", "deal", "timeline", "merge", "relationship"],
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
id: "tables",
|
|
148
|
+
layer: "Data",
|
|
149
|
+
primitive: "tables",
|
|
150
|
+
owns: "Typed working datasets, rows, formulas, AI/tool/waterfall columns, cell state, projects, and run provenance.",
|
|
151
|
+
notFor: "Canonical CRM truth, message cadence, or an off-platform spreadsheet runtime.",
|
|
152
|
+
execution: "Create and run work in hosted OXYGEN Tables; validate a small sample before bounded paid runs.",
|
|
153
|
+
posture: "mixed",
|
|
154
|
+
gatewayTools: ["oxygen_tables_create", "oxygen_columns_add", "oxygen_enrich_column_preview"],
|
|
155
|
+
gatewayCommands: ["tables create", "columns add", "enrich-column preview"],
|
|
156
|
+
skills: ["oxygen-gtm", "oxygen-table-tidy", "oxygen-diagnostics", "oxygen-clay-migration"],
|
|
157
|
+
endpointSections: ["action-columns", "callables", "columns", "company-enrichment", "enrich-column", "enrichment", "projects", "table-action-runs", "table-ingestion-runs", "tables"],
|
|
158
|
+
intentTerms: ["table", "rows", "column", "columns", "dataset", "csv", "import", "enrich", "enrichment", "waterfall", "score", "formula", "ai column", "lookup"],
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
id: "messages",
|
|
162
|
+
layer: "Data",
|
|
163
|
+
primitive: "messages",
|
|
164
|
+
owns: "One-to-one message facts, conversations, direct email, inbox drafts, and replies in existing channel threads.",
|
|
165
|
+
notFor: "Net-new LinkedIn initiation, cadence, enrollment, sender rotation, or reply-stop programs; those belong to Sequences.",
|
|
166
|
+
execution: "Preview and approve a direct email or existing-thread reply; every sent fact stays in the hosted Messages ledger.",
|
|
167
|
+
posture: "external_write",
|
|
168
|
+
gatewayTools: ["oxygen_inbox_send", "oxygen_email_send", "oxygen_messages_query"],
|
|
169
|
+
gatewayCommands: ["inbox send", "email send", "messages query"],
|
|
170
|
+
skills: ["oxygen-unibox"],
|
|
171
|
+
endpointSections: ["email", "inbox", "message-reviews", "messages"],
|
|
172
|
+
intentTerms: ["message", "messages", "reply", "email", "inbox", "conversation", "thread", "direct email", "draft reply", "one off"],
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
id: "posts",
|
|
176
|
+
layer: "Data",
|
|
177
|
+
primitive: "posts",
|
|
178
|
+
owns: "Broadcast post artifacts, author/channel identity, provider IDs, comments, reactions, and performance history.",
|
|
179
|
+
notFor: "One-to-one conversations, delivery scheduling, or generic public LinkedIn provider search.",
|
|
180
|
+
execution: "Read or create the hosted Post artifact; Publishing owns scheduled delivery.",
|
|
181
|
+
posture: "workspace_write",
|
|
182
|
+
gatewayTools: ["oxygen_posts_get", "oxygen_posts_comments_list", "oxygen_posts_reactions_list", "oxygen_posts_create"],
|
|
183
|
+
gatewayCommands: ["posts get", "posts comments", "posts reactions", "posts create"],
|
|
184
|
+
skills: ["oxygen-linkedin-marketing"],
|
|
185
|
+
endpointSections: [],
|
|
186
|
+
intentTerms: ["post artifact", "social post", "post comments", "post reactions", "post performance", "broadcast content"],
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
id: "signals",
|
|
190
|
+
layer: "Data",
|
|
191
|
+
primitive: "signals",
|
|
192
|
+
owns: "Durable typed pulse, engagement, and product events resolved onto records.",
|
|
193
|
+
notFor: "Message bodies, post artifacts, or ad-hoc provider webhooks as private automation state.",
|
|
194
|
+
execution: "Read the hosted signal stream and feed subscriptions, Sequences, or Workflows.",
|
|
195
|
+
posture: "workspace_write",
|
|
196
|
+
gatewayTools: ["oxygen_signals_list", "oxygen_signals_leads_today"],
|
|
197
|
+
gatewayCommands: ["signals list", "signals leads-today", "signals registry"],
|
|
198
|
+
skills: ["oxygen-gtm", "oxygen-linkedin-marketing"],
|
|
199
|
+
endpointSections: ["signals", "signup-leads"],
|
|
200
|
+
intentTerms: ["signal", "signals", "intent", "website visit", "job change", "fundraising", "warm leads", "engager", "follower", "viewer"],
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
id: "dashboards",
|
|
204
|
+
layer: "Data",
|
|
205
|
+
primitive: "dashboards",
|
|
206
|
+
owns: "Curated funnel, channel, spend, and needs-action reporting over native state.",
|
|
207
|
+
notFor: "Arbitrary BI modeling or a separate analytics store.",
|
|
208
|
+
execution: "Compute hosted curated views over Records, Messages, Signals, Sequences, and runs.",
|
|
209
|
+
posture: "read_only",
|
|
210
|
+
gatewayTools: ["oxygen_dashboard_summary"],
|
|
211
|
+
gatewayCommands: ["dashboards summary"],
|
|
212
|
+
skills: ["oxygen-gtm"],
|
|
213
|
+
endpointSections: ["dashboards"],
|
|
214
|
+
intentTerms: ["dashboard", "report", "reporting", "funnel", "metrics", "kpi", "performance", "pipeline summary"],
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
id: "ads",
|
|
218
|
+
layer: "Data",
|
|
219
|
+
primitive: "ads",
|
|
220
|
+
owns: "Competitor ad intelligence today; owned-audience activation is a roadmap boundary.",
|
|
221
|
+
notFor: "Organic Posts, Publishing, or claiming unshipped audience activation.",
|
|
222
|
+
execution: "Discover and run the hosted ad-intelligence provider operation with the normal paid-read gate.",
|
|
223
|
+
posture: "paid_read",
|
|
224
|
+
gatewayTools: ["oxygen_adyntel_ads_search", "oxygen_tools_search"],
|
|
225
|
+
gatewayCommands: ["tools search"],
|
|
226
|
+
skills: ["oxygen-gtm"],
|
|
227
|
+
endpointSections: [],
|
|
228
|
+
intentTerms: ["ad", "ads", "advertising", "ad creative", "competitor ads", "ad intelligence", "meta ads", "linkedin ads"],
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
id: "tags",
|
|
232
|
+
layer: "Data",
|
|
233
|
+
primitive: "tags",
|
|
234
|
+
owns: "The normalized cross-primitive label vocabulary and campaign handle.",
|
|
235
|
+
notFor: "A campaign entity, private per-surface labels, or arbitrary execution state.",
|
|
236
|
+
execution: "Read or mutate tags through the hosted union surface; rename is preview-first.",
|
|
237
|
+
posture: "workspace_write",
|
|
238
|
+
gatewayTools: ["oxygen_tags_list", "oxygen_tags_get", "oxygen_tags_rename"],
|
|
239
|
+
gatewayCommands: ["tags list", "tags get", "tags rename"],
|
|
240
|
+
skills: ["oxygen-gtm"],
|
|
241
|
+
endpointSections: ["tags"],
|
|
242
|
+
intentTerms: ["tag", "tags", "label", "labels", "campaign handle", "grouping", "organize campaign"],
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
id: "sequences",
|
|
246
|
+
layer: "Action",
|
|
247
|
+
primitive: "sequences",
|
|
248
|
+
owns: "Net-new LinkedIn outreach plus versioned multichannel programs, cadence, enrollment, sender limits, suppression, reply-stop, and dispatch.",
|
|
249
|
+
notFor: "A reply in an existing conversation or a direct one-off email; use Messages. Not for general deterministic automation.",
|
|
250
|
+
execution: "Use the one-step gateway for new LinkedIn initiation or create/enroll/start a hosted campaign with bounded send authority.",
|
|
251
|
+
posture: "external_write",
|
|
252
|
+
gatewayTools: ["oxygen_sequences_send", "oxygen_sequences_create", "oxygen_sequences_enroll", "oxygen_sequences_start", "oxygen_sequences_list"],
|
|
253
|
+
gatewayCommands: ["sequences send", "sequences create", "sequences enroll", "sequences start", "sequences list"],
|
|
254
|
+
skills: ["oxygen-sequencer"],
|
|
255
|
+
endpointSections: ["senders", "sequencer", "sequences", "spintax", "suppressions", "voice"],
|
|
256
|
+
intentTerms: ["sequence", "campaign", "cadence", "enroll", "outreach", "linkedin message", "linkedin dm", "nurture", "follow up", "sender rotation", "stop on reply"],
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
id: "publishing",
|
|
260
|
+
layer: "Action",
|
|
261
|
+
primitive: "publishing",
|
|
262
|
+
owns: "Approval-gated scheduling, dispatch, retries, review, and attempt provenance for broadcast Posts.",
|
|
263
|
+
notFor: "One-to-one messaging, outreach campaigns, or general automation.",
|
|
264
|
+
execution: "Create and schedule on OXYGEN; explicit approval releases the hosted publisher.",
|
|
265
|
+
posture: "external_write",
|
|
266
|
+
gatewayTools: ["oxygen_publishing_posts_create", "oxygen_publishing_posts_list", "oxygen_publishing_posts_approve"],
|
|
267
|
+
gatewayCommands: ["publishing posts create", "publishing posts list", "publishing posts approve"],
|
|
268
|
+
skills: ["oxygen-linkedin-marketing"],
|
|
269
|
+
endpointSections: ["publishing"],
|
|
270
|
+
intentTerms: ["publish", "publishing", "schedule post", "content calendar", "posting calendar", "approve post", "social publishing"],
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
id: "workflows",
|
|
274
|
+
layer: "Action",
|
|
275
|
+
primitive: "workflows",
|
|
276
|
+
owns: "Deterministic hosted automation definitions, versions, triggers, branching, retries, approvals, modes, and durable runs.",
|
|
277
|
+
notFor: "Local cron, client-side execution, adaptive Agent goals, or outreach cadence already owned by Sequences.",
|
|
278
|
+
execution: "Author locally if useful, then schema/lint/apply and call the Workflow on OXYGEN workers; outbound uses internal oxygen.sequence_enroll against an already active bounded Sequence.",
|
|
279
|
+
posture: "mixed",
|
|
280
|
+
gatewayTools: ["oxygen_workflows_schema", "oxygen_workflows_lint", "oxygen_workflows_apply", "oxygen_workflows_call", "oxygen_workflows_tail"],
|
|
281
|
+
gatewayCommands: ["workflows schema", "workflows lint", "workflows apply", "workflows call", "workflows tail"],
|
|
282
|
+
skills: ["oxygen-workflow-authoring"],
|
|
283
|
+
endpointSections: ["workflows"],
|
|
284
|
+
intentTerms: ["workflow", "automation", "automate", "webhook", "cron", "trigger", "branch", "retry", "orchestrate", "scheduled job", "deterministic graph"],
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
id: "agents",
|
|
288
|
+
layer: "Action",
|
|
289
|
+
primitive: "agents",
|
|
290
|
+
owns: "Adaptive governed worker definitions, versions, authorization, context, triggers, threads, checkpoints, inference, and first-class runs.",
|
|
291
|
+
notFor: "A known deterministic graph that belongs in Workflows or an opaque uploaded runtime.",
|
|
292
|
+
execution: "Publish and run a hosted governed Agent with explicit tool authority and a separate bounded spend ceiling.",
|
|
293
|
+
posture: "mixed",
|
|
294
|
+
gatewayTools: ["oxygen_agent_list", "oxygen_agent_create", "oxygen_agent_run"],
|
|
295
|
+
gatewayCommands: ["agent list", "agent create", "agent run"],
|
|
296
|
+
skills: ["oxygen-gtm"],
|
|
297
|
+
endpointSections: ["agent", "notetaker"],
|
|
298
|
+
intentTerms: ["agent", "adaptive", "goal directed", "autonomous", "persistent thread", "checkpoint", "standing job", "notetaker"],
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
id: "observability",
|
|
302
|
+
layer: "Action",
|
|
303
|
+
primitive: "observability",
|
|
304
|
+
owns: "The cross-primitive read lens for runs, timelines, approvals, costs, failures, retries, and outputs.",
|
|
305
|
+
notFor: "Operational infrastructure logs or a second execution engine.",
|
|
306
|
+
execution: "Inspect hosted run state and decide pending approvals through native read/control surfaces.",
|
|
307
|
+
posture: "read_only",
|
|
308
|
+
gatewayTools: ["oxygen_observability_runs", "oxygen_observability_approvals", "oxygen_observability_events"],
|
|
309
|
+
gatewayCommands: ["observability runs", "observability approvals", "observability events"],
|
|
310
|
+
skills: ["oxygen-diagnostics"],
|
|
311
|
+
endpointSections: ["observability", "runs"],
|
|
312
|
+
intentTerms: ["observability", "run", "runs", "failure", "failed", "retry", "provenance", "cost", "approval", "what is running"],
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
id: "sourcing-and-provider-tools",
|
|
316
|
+
layer: "External",
|
|
317
|
+
primitive: null,
|
|
318
|
+
owns: "Company/people sourcing, one-shot contact finding, provider-operation discovery, and durable search plans feeding Tables.",
|
|
319
|
+
notFor: "Enriching rows that already exist; use native table columns and waterfalls. Not for raw provider selection when a native gateway exists.",
|
|
320
|
+
execution: "Plan or preview the hosted search, then run with an explicit scope and credit ceiling; hydrate one provider descriptor only when needed.",
|
|
321
|
+
posture: "paid_read",
|
|
322
|
+
gatewayTools: ["oxygen_search_plan", "oxygen_sourcing_plan", "oxygen_find_company", "oxygen_tools_search"],
|
|
323
|
+
gatewayCommands: ["search plan", "sourcing plan", "find company", "tools search"],
|
|
324
|
+
skills: ["oxygen-gtm"],
|
|
325
|
+
endpointSections: ["companies", "find", "lead-sourcing", "people", "search", "sourcing", "tools", "verify"],
|
|
326
|
+
intentTerms: ["find companies", "find people", "source leads", "build a list", "tam", "prospect", "provider", "tool catalog", "find email", "find phone"],
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
id: "linkedin-public-research",
|
|
330
|
+
layer: "External",
|
|
331
|
+
primitive: null,
|
|
332
|
+
owns: "Cookieless public or third-party LinkedIn profiles, companies, posts, search, reactions, comments, and engagers through native scraper operations.",
|
|
333
|
+
notFor: "The workspace account network/inbox or any LinkedIn write; those require the connected LinkedIn surface.",
|
|
334
|
+
execution: "For a known post's engagers, preview the durable engagement harvest; for other reads, search `scraper.*`, hydrate one descriptor, and run without a connected-account quota.",
|
|
335
|
+
posture: "paid_read",
|
|
336
|
+
gatewayTools: ["oxygen_tools_search", "oxygen_tools_get"],
|
|
337
|
+
gatewayCommands: ["tools search", "tools get"],
|
|
338
|
+
skills: ["oxygen-gtm", "oxygen-linkedin-marketing"],
|
|
339
|
+
endpointSections: [],
|
|
340
|
+
intentTerms: ["public linkedin", "third party linkedin", "linkedin profile", "linkedin company", "linkedin post", "linkedin comments", "linkedin reactions", "linkedin engagers", "harvest", "cookieless"],
|
|
341
|
+
negativeTerms: ["my linkedin", "our linkedin", "own linkedin", "connected account", "inbox", "send", "invite", "publish"],
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
id: "connected-integrations",
|
|
345
|
+
layer: "External",
|
|
346
|
+
primitive: null,
|
|
347
|
+
owns: "Connected SaaS accounts, OAuth/BYOK readiness, custom integration manifests, and provider actions that lack a native primitive gateway.",
|
|
348
|
+
notFor: "Recreating native Tables, Messages, Sequences, Publishing, or Workflows through a generic provider action.",
|
|
349
|
+
execution: "Inspect readiness, then connect or call the hosted integration under its exact write/spend gate.",
|
|
350
|
+
posture: "mixed",
|
|
351
|
+
gatewayTools: ["oxygen_integrations_list", "oxygen_integrations_connect", "oxygen_integrations_list_actions"],
|
|
352
|
+
gatewayCommands: ["integrations list", "integrations connect", "custom-integrations list"],
|
|
353
|
+
skills: ["oxygen-gtm"],
|
|
354
|
+
endpointSections: ["custom-integrations", "integrations"],
|
|
355
|
+
intentTerms: ["integration", "integrations", "connect provider", "oauth", "byok", "custom http", "custom integration", "connection readiness"],
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
id: "sending-infrastructure",
|
|
359
|
+
layer: "External",
|
|
360
|
+
primitive: null,
|
|
361
|
+
owns: "Sending domains, managed/BYOK mailboxes, warmup, deliverability, egress IPs, and infrastructure health beneath Sequences.",
|
|
362
|
+
notFor: "Writing campaign copy or sending outside a Sequence/Message owner.",
|
|
363
|
+
execution: "Inspect or provision hosted sending infrastructure with explicit recurring-cost and external-write approval.",
|
|
364
|
+
posture: "mixed",
|
|
365
|
+
gatewayTools: ["oxygen_mailboxes_list", "oxygen_domains_list", "oxygen_mailboxes_health"],
|
|
366
|
+
gatewayCommands: ["mailboxes list", "domains list", "mailboxes health"],
|
|
367
|
+
skills: ["oxygen-email-infra", "oxygen-deliverability", "oxygen-sequencer"],
|
|
368
|
+
endpointSections: ["deliverability", "domains", "egress", "mailboxes", "managed-inboxes"],
|
|
369
|
+
intentTerms: ["mailbox", "mailboxes", "sending domain", "dns", "warmup", "deliverability", "placement", "egress ip", "email infrastructure", "managed inbox"],
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
id: "connected-linkedin",
|
|
373
|
+
layer: "External",
|
|
374
|
+
primitive: null,
|
|
375
|
+
owns: "The workspace LinkedIn account network/private data and connected-account writes used by Signals, Messages, Sequences, and Publishing.",
|
|
376
|
+
notFor: "Ordinary public or third-party LinkedIn research; use the cookieless native scraper.",
|
|
377
|
+
execution: "Use the owning primitive gateway; the connected account provides identity and transport, not a competing product runtime.",
|
|
378
|
+
posture: "mixed",
|
|
379
|
+
gatewayTools: ["oxygen_senders_list", "oxygen_linkedin_connections_import", "oxygen_inbox_list"],
|
|
380
|
+
gatewayCommands: ["senders list", "connections import", "inbox list"],
|
|
381
|
+
skills: ["oxygen-linkedin-marketing", "oxygen-sequencer", "oxygen-unibox"],
|
|
382
|
+
endpointSections: ["linkedin"],
|
|
383
|
+
intentTerms: ["my linkedin", "our linkedin", "own linkedin", "connected linkedin", "connections", "followers", "profile viewers", "sales navigator", "recruiter", "linkedin inbox"],
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
id: "connected-whatsapp",
|
|
387
|
+
layer: "External",
|
|
388
|
+
primitive: null,
|
|
389
|
+
owns: "Connected WhatsApp accounts, account limits, warm existing-thread sends, and transport beneath Messages/Sequences.",
|
|
390
|
+
notFor: "A generic chat executor: replies belong to Messages and cold/multistep outreach belongs to Sequences.",
|
|
391
|
+
execution: "Inspect the connected account, then route reply or initiation intent to the owning native primitive.",
|
|
392
|
+
posture: "external_write",
|
|
393
|
+
gatewayTools: ["oxygen_whatsapp_accounts_list", "oxygen_inbox_send", "oxygen_sequences_create"],
|
|
394
|
+
gatewayCommands: ["whatsapp accounts", "inbox send", "sequences create"],
|
|
395
|
+
skills: ["oxygen-unibox", "oxygen-sequencer"],
|
|
396
|
+
endpointSections: ["whatsapp"],
|
|
397
|
+
intentTerms: ["whatsapp", "whatsapp account", "whatsapp reply", "whatsapp outreach", "warm send"],
|
|
398
|
+
},
|
|
399
|
+
];
|
|
400
|
+
export const OXYGEN_PRIMITIVE_ROUTES = OXYGEN_CAPABILITY_ROUTES
|
|
401
|
+
.filter((card) => card.primitive !== null);
|
|
402
|
+
const ROUTE_BY_ID = new Map(OXYGEN_CAPABILITY_ROUTES.map((card) => [card.id, card]));
|
|
403
|
+
const ROUTE_BY_PRIMITIVE = new Map(OXYGEN_PRIMITIVE_ROUTES.map((card) => [card.primitive, card]));
|
|
404
|
+
const NORMALIZED_PRIMITIVES = [...RECIPE_PRIMITIVES].sort();
|
|
405
|
+
const NORMALIZED_ROUTE_PRIMITIVES = OXYGEN_PRIMITIVE_ROUTES.map((card) => card.primitive).sort();
|
|
406
|
+
if (NORMALIZED_PRIMITIVES.join("|") !== NORMALIZED_ROUTE_PRIMITIVES.join("|")) {
|
|
407
|
+
throw new Error("OXYGEN capability routes must cover the shared fifteen-primitive catalog exactly.");
|
|
408
|
+
}
|
|
409
|
+
export function getCapabilityRoute(id) {
|
|
410
|
+
return ROUTE_BY_ID.get(id.trim().toLowerCase()) ?? null;
|
|
411
|
+
}
|
|
412
|
+
export function getCapabilityRouteMatch(id) {
|
|
413
|
+
const card = getCapabilityRoute(id);
|
|
414
|
+
if (!card)
|
|
415
|
+
return null;
|
|
416
|
+
const recommendations = recommendationsFor(card, normalizeIntent(id));
|
|
417
|
+
return {
|
|
418
|
+
card,
|
|
419
|
+
recommendedTools: recommendations.tools,
|
|
420
|
+
recommendedCommands: recommendations.commands,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
export function inferCapabilityRoute(query) {
|
|
424
|
+
const normalized = normalizeIntent(query);
|
|
425
|
+
if (!normalized)
|
|
426
|
+
return null;
|
|
427
|
+
const explicit = explicitCapabilityIntent(normalized);
|
|
428
|
+
const card = explicit ?? highestScoringRoute(normalized);
|
|
429
|
+
if (!card)
|
|
430
|
+
return null;
|
|
431
|
+
const recommendations = recommendationsFor(card, normalized);
|
|
432
|
+
return {
|
|
433
|
+
card,
|
|
434
|
+
recommendedTools: recommendations.tools,
|
|
435
|
+
recommendedCommands: recommendations.commands,
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
export function inferPrimitiveRoute(query) {
|
|
439
|
+
const route = inferCapabilityRoute(query);
|
|
440
|
+
if (!route || route.card.primitive === null)
|
|
441
|
+
return null;
|
|
442
|
+
return route;
|
|
443
|
+
}
|
|
444
|
+
export function serializeCapabilityRoute(route) {
|
|
445
|
+
if (!route)
|
|
446
|
+
return null;
|
|
447
|
+
return {
|
|
448
|
+
capability_id: route.card.id,
|
|
449
|
+
layer: route.card.layer,
|
|
450
|
+
primitive: route.card.primitive,
|
|
451
|
+
owns: route.card.owns,
|
|
452
|
+
not_for: route.card.notFor,
|
|
453
|
+
execution: route.card.execution,
|
|
454
|
+
posture: route.card.posture,
|
|
455
|
+
skills: route.card.skills,
|
|
456
|
+
endpoint_sections: route.card.endpointSections,
|
|
457
|
+
recommended_commands: route.recommendedCommands,
|
|
458
|
+
recommended_tools: route.recommendedTools,
|
|
459
|
+
hydrate: {
|
|
460
|
+
cli: "oxygen commands get <exact-command> --json",
|
|
461
|
+
mcp: "oxygen_capabilities_schema",
|
|
462
|
+
},
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
function normalizeIntent(query) {
|
|
466
|
+
return query.toLowerCase().replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
|
|
467
|
+
}
|
|
468
|
+
function explicitCapabilityIntent(query) {
|
|
469
|
+
if (isHostedWorkflowIntent(query))
|
|
470
|
+
return ROUTE_BY_PRIMITIVE.get("workflows") ?? null;
|
|
471
|
+
// A deferred acquisition motion starts with the public-data owner. This keeps
|
|
472
|
+
// "find/qualify now, contact later" from skipping straight to the final write
|
|
473
|
+
// step; the recommendation still hands the eventual initiation to Sequences.
|
|
474
|
+
if (isPublicLinkedInRead(query) && isDeferredLinkedInOutreach(query)) {
|
|
475
|
+
return ROUTE_BY_ID.get("linkedin-public-research") ?? null;
|
|
476
|
+
}
|
|
477
|
+
// When one ask combines public LinkedIn research with initiating a new
|
|
478
|
+
// conversation now, the external write owner wins. The Sequences
|
|
479
|
+
// recommendation still exposes the native scraper discovery step for the
|
|
480
|
+
// research input.
|
|
481
|
+
if (isNetNewLinkedInInitiation(query))
|
|
482
|
+
return ROUTE_BY_PRIMITIVE.get("sequences") ?? null;
|
|
483
|
+
if (isPublicLinkedInRead(query))
|
|
484
|
+
return ROUTE_BY_ID.get("linkedin-public-research") ?? null;
|
|
485
|
+
if (/\b(my|our|own)\b.{0,40}\blinkedin\b.{0,40}\b(post )?engagers?\b/.test(query)) {
|
|
486
|
+
return ROUTE_BY_PRIMITIVE.get("signals") ?? null;
|
|
487
|
+
}
|
|
488
|
+
if (/\b(recipe|playbook|proven play|what should i do)\b/.test(query)) {
|
|
489
|
+
return ROUTE_BY_PRIMITIVE.get("recipes") ?? null;
|
|
490
|
+
}
|
|
491
|
+
if (/\btable\b.{0,24}\b(action |ingestion )?runs?\b/.test(query)) {
|
|
492
|
+
return ROUTE_BY_PRIMITIVE.get("tables") ?? null;
|
|
493
|
+
}
|
|
494
|
+
if (/\b(message )?reviews?\b/.test(query))
|
|
495
|
+
return ROUTE_BY_PRIMITIVE.get("messages") ?? null;
|
|
496
|
+
if (/\b(tag|tags|label|labels)\b/.test(query))
|
|
497
|
+
return ROUTE_BY_PRIMITIVE.get("tags") ?? null;
|
|
498
|
+
if (/\b(disposable|working)\b.{0,30}\b(list|dataset|table)\b|\b(prospect|sourcing) table\b/.test(query)) {
|
|
499
|
+
return ROUTE_BY_PRIMITIVE.get("tables") ?? null;
|
|
500
|
+
}
|
|
501
|
+
if (/\bwhatsapp\b.{0,30}\b(account|connect|limits?|sync)\b/.test(query)) {
|
|
502
|
+
return ROUTE_BY_ID.get("connected-whatsapp") ?? null;
|
|
503
|
+
}
|
|
504
|
+
if (!isNetNewLinkedInInitiation(query)
|
|
505
|
+
&& (/\b(one[ -]off|ad[ -]hoc|just once|reply once|single message|direct message|direct email|no cadence)\b/.test(query)
|
|
506
|
+
|| /\b(reply|respond|follow up)\b.{0,30}\b(conversation|thread|email|linkedin|whatsapp|dm)\b/.test(query))) {
|
|
507
|
+
return ROUTE_BY_PRIMITIVE.get("messages") ?? null;
|
|
508
|
+
}
|
|
509
|
+
if (/\b(my|our|own|connected)\b.{0,40}\blinkedin\b|\b(sales navigator|salesnav|recruiter|profile viewers?|linkedin inbox)\b/.test(query)) {
|
|
510
|
+
return ROUTE_BY_ID.get("connected-linkedin") ?? null;
|
|
511
|
+
}
|
|
512
|
+
if (/\b(publish|schedule|approve)\b.{0,24}\b(post|content)\b|\bcontent calendar\b/.test(query)) {
|
|
513
|
+
return ROUTE_BY_PRIMITIVE.get("publishing") ?? null;
|
|
514
|
+
}
|
|
515
|
+
if (/\b(sequence|campaign|cadence|enroll|nurture)\b/.test(query)
|
|
516
|
+
|| /\b(day\s*\d+|days?\s+\d|multi[ -]step|rotate senders?|sender rotation|stop on reply|until (?:they )?reply)\b/.test(query)) {
|
|
517
|
+
return ROUTE_BY_PRIMITIVE.get("sequences") ?? null;
|
|
518
|
+
}
|
|
519
|
+
if (/\b(reply|respond)\b.{0,30}\b(conversation|thread|email|linkedin|whatsapp|dm)\b/.test(query)) {
|
|
520
|
+
return ROUTE_BY_PRIMITIVE.get("messages") ?? null;
|
|
521
|
+
}
|
|
522
|
+
if (/\b(find emails?|find phones?|find companies|find people|source (?:leads?|a list|companies|people)|build (?:me )?a list|tam|prospect)\b/.test(query)) {
|
|
523
|
+
return ROUTE_BY_ID.get("sourcing-and-provider-tools") ?? null;
|
|
524
|
+
}
|
|
525
|
+
if (/\b(agent|adaptive|goal[ -]directed|persistent thread|checkpoint|standing job)\b/.test(query)) {
|
|
526
|
+
return ROUTE_BY_PRIMITIVE.get("agents") ?? null;
|
|
527
|
+
}
|
|
528
|
+
return null;
|
|
529
|
+
}
|
|
530
|
+
function highestScoringRoute(query) {
|
|
531
|
+
let best = null;
|
|
532
|
+
for (const card of OXYGEN_CAPABILITY_ROUTES) {
|
|
533
|
+
let score = 0;
|
|
534
|
+
for (const term of card.intentTerms) {
|
|
535
|
+
if (query.includes(term))
|
|
536
|
+
score += term.includes(" ") ? 6 : 2;
|
|
537
|
+
}
|
|
538
|
+
for (const term of card.negativeTerms ?? []) {
|
|
539
|
+
if (query.includes(term))
|
|
540
|
+
score -= term.includes(" ") ? 8 : 3;
|
|
541
|
+
}
|
|
542
|
+
if (score > (best?.score ?? 0))
|
|
543
|
+
best = { card, score };
|
|
544
|
+
}
|
|
545
|
+
return best?.card ?? null;
|
|
546
|
+
}
|
|
547
|
+
function recommendationsFor(card, query) {
|
|
548
|
+
if (card.id === "linkedin-public-research" && isPublicLinkedInEngagerHarvest(query)) {
|
|
549
|
+
const motion = isLinkedInEngagerMotion(query);
|
|
550
|
+
return {
|
|
551
|
+
tools: [
|
|
552
|
+
...(motion ? ["oxygen_recipes_list"] : []),
|
|
553
|
+
"oxygen_engagement_harvest",
|
|
554
|
+
"oxygen_engagement_harvest_status",
|
|
555
|
+
"oxygen_tools_search",
|
|
556
|
+
"oxygen_tools_get",
|
|
557
|
+
...(isDeferredLinkedInOutreach(query)
|
|
558
|
+
? ["oxygen_sequences_send", "oxygen_sequences_list"]
|
|
559
|
+
: []),
|
|
560
|
+
],
|
|
561
|
+
commands: [
|
|
562
|
+
...(motion ? ["recipes list"] : []),
|
|
563
|
+
"engagement harvest",
|
|
564
|
+
"engagement status",
|
|
565
|
+
"tools search",
|
|
566
|
+
"tools get",
|
|
567
|
+
...(isDeferredLinkedInOutreach(query)
|
|
568
|
+
? ["sequences send", "sequences list"]
|
|
569
|
+
: []),
|
|
570
|
+
],
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
if (card.primitive === "tables") {
|
|
574
|
+
if (/\b(table )?(action )?runs?\b/.test(query)) {
|
|
575
|
+
return {
|
|
576
|
+
tools: ["oxygen_table_runs_get", "oxygen_table_runs_items", "oxygen_table_runs_wait", "oxygen_table_runs_retry_failed"],
|
|
577
|
+
commands: ["table-runs get", "table-runs items", "table-runs wait", "table-runs retry-failed"],
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
if (/\b(waterfall|enrich|enrichment|work email|mobile phone)\b/.test(query)) {
|
|
581
|
+
return {
|
|
582
|
+
tools: ["oxygen_enrich_column_preview", "oxygen_columns_add", "oxygen_enrich_column_run", "oxygen_table_runs_get"],
|
|
583
|
+
commands: ["enrich-column preview", "columns add", "enrich-column run", "table-runs get"],
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
if (/\b(ai column|classif(?:y|ication)|extract(?:ion)?|scor(?:e|ing)|summari[sz](?:e|ation)|draft(?:ing)?|research)\b/.test(query)) {
|
|
587
|
+
return {
|
|
588
|
+
tools: ["oxygen_columns_add", "oxygen_columns_run", "oxygen_tables_describe", "oxygen_context_resolve"],
|
|
589
|
+
commands: ["columns add", "columns run", "tables describe", "context resolve"],
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
if (/\bformula|deterministic transform\b/.test(query)) {
|
|
593
|
+
return {
|
|
594
|
+
tools: ["oxygen_formulas_list", "oxygen_formulas_validate", "oxygen_columns_add"],
|
|
595
|
+
commands: ["formulas list", "formulas validate", "columns add"],
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
if (card.primitive === "messages") {
|
|
600
|
+
if (/\b(message )?reviews?\b/.test(query)) {
|
|
601
|
+
return {
|
|
602
|
+
tools: ["oxygen_reviews_list", "oxygen_reviews_next", "oxygen_reviews_decide"],
|
|
603
|
+
commands: ["reviews list", "reviews next", "reviews decide"],
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
const existingThread = /\b(reply|respond|conversation|thread|inbox|existing)\b/.test(query);
|
|
607
|
+
if (/\bemail\b/.test(query) && !existingThread) {
|
|
608
|
+
return {
|
|
609
|
+
tools: ["oxygen_email_send", "oxygen_inbox_send", "oxygen_messages_query"],
|
|
610
|
+
commands: ["email send", "inbox send", "messages query"],
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
if (card.primitive === "sequences") {
|
|
615
|
+
if (isNetNewLinkedInInitiation(query)) {
|
|
616
|
+
const publicResearch = isPublicLinkedInRead(query);
|
|
617
|
+
const harvestEngagers = publicResearch && isPublicLinkedInEngagerHarvest(query);
|
|
618
|
+
return {
|
|
619
|
+
tools: [
|
|
620
|
+
"oxygen_sequences_send",
|
|
621
|
+
...(harvestEngagers
|
|
622
|
+
? ["oxygen_engagement_harvest", "oxygen_engagement_harvest_status"]
|
|
623
|
+
: publicResearch
|
|
624
|
+
? ["oxygen_tools_search", "oxygen_tools_get"]
|
|
625
|
+
: []),
|
|
626
|
+
"oxygen_senders_list",
|
|
627
|
+
"oxygen_sequences_list",
|
|
628
|
+
],
|
|
629
|
+
commands: [
|
|
630
|
+
"sequences send",
|
|
631
|
+
...(harvestEngagers
|
|
632
|
+
? ["engagement harvest", "engagement status"]
|
|
633
|
+
: publicResearch
|
|
634
|
+
? ["tools search", "tools get"]
|
|
635
|
+
: []),
|
|
636
|
+
"senders list",
|
|
637
|
+
"sequences list",
|
|
638
|
+
],
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
if (/\benroll/.test(query)) {
|
|
642
|
+
return {
|
|
643
|
+
tools: ["oxygen_sequences_enroll", "oxygen_sequences_create", "oxygen_sequences_start", "oxygen_sequences_list"],
|
|
644
|
+
commands: ["sequences enroll", "sequences create", "sequences start", "sequences list"],
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
if (/\b(start|launch|run|activate)\b/.test(query)) {
|
|
648
|
+
return {
|
|
649
|
+
tools: ["oxygen_sequences_start", "oxygen_sequences_list", "oxygen_sequences_create", "oxygen_sequences_enroll"],
|
|
650
|
+
commands: ["sequences start", "sequences list", "sequences create", "sequences enroll"],
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
return {
|
|
654
|
+
tools: ["oxygen_sequences_create", "oxygen_sequences_enroll", "oxygen_sequences_start", "oxygen_sequences_list", "oxygen_sequences_send"],
|
|
655
|
+
commands: ["sequences create", "sequences enroll", "sequences start", "sequences list", "sequences send"],
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
if (card.primitive === "workflows") {
|
|
659
|
+
if (isLinkedInEngagerMotion(query)) {
|
|
660
|
+
return {
|
|
661
|
+
tools: [
|
|
662
|
+
"oxygen_recipes_list",
|
|
663
|
+
"oxygen_blueprints_describe",
|
|
664
|
+
"oxygen_blueprints_preflight",
|
|
665
|
+
"oxygen_tools_get",
|
|
666
|
+
"oxygen_sequences_list",
|
|
667
|
+
],
|
|
668
|
+
commands: [
|
|
669
|
+
"recipes list",
|
|
670
|
+
"blueprints describe",
|
|
671
|
+
"blueprints preflight",
|
|
672
|
+
"tools get",
|
|
673
|
+
"sequences list",
|
|
674
|
+
],
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
if (/\b(workflow )?templates?\b/.test(query)) {
|
|
678
|
+
return {
|
|
679
|
+
tools: ["oxygen_workflow_templates_search", "oxygen_workflow_templates_describe", "oxygen_workflow_templates_preflight", "oxygen_workflow_templates_apply"],
|
|
680
|
+
commands: ["workflows templates search", "workflows templates describe", "workflows templates preflight", "workflows templates apply"],
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
if (isNetNewLinkedInInitiation(query) || /\b(outreach|sequence|enroll|message)\b/.test(query)) {
|
|
684
|
+
return {
|
|
685
|
+
tools: ["oxygen_workflows_schema", "oxygen_workflows_lint", "oxygen_workflows_apply", "oxygen_tools_get", "oxygen_sequences_list", "oxygen_sequences_start"],
|
|
686
|
+
commands: ["workflows schema", "workflows lint", "workflows apply", "tools get", "sequences list", "sequences start"],
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
if (/\b(tail|inspect|status|events?|failures?)\b/.test(query)) {
|
|
690
|
+
return {
|
|
691
|
+
tools: ["oxygen_workflows_tail", "oxygen_workflows_list", "oxygen_workflows_call"],
|
|
692
|
+
commands: ["workflows tail", "workflows list", "workflows call"],
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
if (/\b(run|call|execute)\b/.test(query) && !/\b(build|create|author|design|apply)\b/.test(query)) {
|
|
696
|
+
return {
|
|
697
|
+
tools: ["oxygen_workflows_call", "oxygen_workflows_tail", "oxygen_workflows_schema"],
|
|
698
|
+
commands: ["workflows call", "workflows tail", "workflows schema"],
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
if (card.primitive === "signals" && /\blinkedin\b.{0,40}\bengagers?\b/.test(query)) {
|
|
703
|
+
return {
|
|
704
|
+
tools: ["oxygen_engagement_list_engagers", "oxygen_signals_list", "oxygen_signals_leads_today"],
|
|
705
|
+
commands: ["engagement list", "signals list", "signals leads-today"],
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
if (card.id === "connected-whatsapp" && /\b(account|connect|limits?|sync)\b/.test(query)) {
|
|
709
|
+
return {
|
|
710
|
+
tools: ["oxygen_whatsapp_accounts_list", "oxygen_whatsapp_get", "oxygen_whatsapp_limits_get", "oxygen_whatsapp_connect"],
|
|
711
|
+
commands: ["whatsapp accounts list", "whatsapp get", "whatsapp limits get", "whatsapp connect"],
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
return { tools: [...card.gatewayTools], commands: [...card.gatewayCommands] };
|
|
715
|
+
}
|
|
716
|
+
function isNetNewLinkedInInitiation(query) {
|
|
717
|
+
const mentionsLinkedIn = /\blinkedin\b|\bdm\b/.test(query);
|
|
718
|
+
const startsConversation = /\b(send|message|dm|contact|reach out|initiate|start)\b/.test(query)
|
|
719
|
+
|| /\bnew\b.{0,40}\bconversation\b/.test(query);
|
|
720
|
+
if (!mentionsLinkedIn || !startsConversation)
|
|
721
|
+
return false;
|
|
722
|
+
// "Conversation" can describe either side of the boundary. New/start is an
|
|
723
|
+
// initiation; reply/existing/thread/inbox is continuation state in Messages.
|
|
724
|
+
if (/\b(reply|respond|existing|thread|inbox)\b/.test(query))
|
|
725
|
+
return false;
|
|
726
|
+
return !/\b(sequence|campaign|cadence|enroll|nurture|multi[ -]step|multi[ -]recipient|leads|contacts|recipients|audience|rotate senders?|stop on reply|day\s*\d+)\b/.test(query);
|
|
727
|
+
}
|
|
728
|
+
function isHostedWorkflowIntent(query) {
|
|
729
|
+
const strongWorkflowLanguage = /\b(workflow|automation|automate|automatically|webhook|cron|event trigger|branching?|retr(?:y|ies)|orchestrat(?:e|ion)|scheduled job|deterministic graph)\b/.test(query);
|
|
730
|
+
const cadenceLanguage = /\b(sequence|campaign|cadence|day\s*\d+|multi[ -]step|rotate senders?|sender rotation|stop on reply|until (?:they )?reply)\b/.test(query);
|
|
731
|
+
const workflowMechanics = /\b(webhook|cron|event trigger|triggered by|branching?|retr(?:y|ies)|orchestrat(?:e|ion)|scheduled job|deterministic graph|automatically)\b/.test(query)
|
|
732
|
+
|| /\bwhen\b.{0,50}\b(signs? up|created|updated|changes?|happens?|received)\b/.test(query);
|
|
733
|
+
if (cadenceLanguage && !workflowMechanics)
|
|
734
|
+
return false;
|
|
735
|
+
if (strongWorkflowLanguage)
|
|
736
|
+
return true;
|
|
737
|
+
if (cadenceLanguage)
|
|
738
|
+
return false;
|
|
739
|
+
return /\b(nightly|hourly|daily|weekly|every (?:monday|tuesday|wednesday|thursday|friday|saturday|sunday|day|night|week|month))\b/.test(query)
|
|
740
|
+
|| (/\bschedule(?:d)?\b/.test(query) && !/\bpost|content\b/.test(query));
|
|
741
|
+
}
|
|
742
|
+
function isPublicLinkedInRead(query) {
|
|
743
|
+
if (!query.includes("linkedin"))
|
|
744
|
+
return false;
|
|
745
|
+
const disclaimsConnectedAccount = /\b(without|no|not using|does not require)\b.{0,24}\bconnected(?: linkedin)? account\b/.test(query);
|
|
746
|
+
const connectedOwnership = !disclaimsConnectedAccount
|
|
747
|
+
&& /\b(my|our|own|connected|connections|followers|inbox|messages|recruiter|sales\s*navigator|salesnav|unipile|viewers)\b/.test(query);
|
|
748
|
+
if (connectedOwnership)
|
|
749
|
+
return false;
|
|
750
|
+
return /\b(comments?|companies|company|competitor|cookieless|engagers?|harvest|posts?|profiles?|public|reactions?|reactors?|scrape|scraper|search|third[ -]party)\b/.test(query);
|
|
751
|
+
}
|
|
752
|
+
function isPublicLinkedInEngagerHarvest(query) {
|
|
753
|
+
return /\bpost\b/.test(query)
|
|
754
|
+
&& /\b(engagers?|engaged|react(?:ors?|ing|ed|ions?)|commenters?|harvest)\b/.test(query);
|
|
755
|
+
}
|
|
756
|
+
function isDeferredLinkedInOutreach(query) {
|
|
757
|
+
if (!isNetNewLinkedInInitiation(query))
|
|
758
|
+
return false;
|
|
759
|
+
return /\b(later|eventually|after (?:they|we|i)? ?(?:are )?qualif(?:y|ied)|once (?:they|we|i)? ?(?:are )?qualif(?:y|ied)|prepare|ready)\b/.test(query)
|
|
760
|
+
|| /\bwithout\b.{0,30}\b(?:running|sending|contacting|messaging)\b.{0,20}\b(?:now|today)\b/.test(query)
|
|
761
|
+
|| /\b(?:do not|don t|not)\b.{0,20}\b(?:run|send|contact|message)\b.{0,20}\b(?:now|today)\b/.test(query);
|
|
762
|
+
}
|
|
763
|
+
function isLinkedInEngagerMotion(query) {
|
|
764
|
+
return isPublicLinkedInEngagerHarvest(query)
|
|
765
|
+
&& /\b(competitor|daily|repeatable|monitor|motion|qualif(?:y|ied)|workflow|later|eventually)\b/.test(query);
|
|
766
|
+
}
|