@oxygen-agent/cli 1.1014.1600 → 1.1014.1763
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-families/program.js +4 -0
- package/dist/command-manifest.js +18 -3
- package/dist/command-support.js +1 -1
- package/dist/commands/admin.js +82 -1
- package/dist/commands/billing.js +1 -1
- package/dist/commands/copilot.js +29 -7
- package/dist/commands/custom-integrations.js +13 -0
- package/dist/commands/domains.js +7 -0
- package/dist/commands/email-assets.d.ts +3 -0
- package/dist/commands/email-assets.js +78 -0
- package/dist/commands/email-templates.d.ts +3 -0
- package/dist/commands/email-templates.js +101 -0
- package/dist/commands/inbox.js +1 -1
- package/dist/commands/integrations.js +5 -1
- package/dist/commands/mailboxes.js +26 -6
- package/dist/commands/managed-inboxes.js +2 -2
- package/dist/commands/senders.js +4 -4
- package/dist/commands/sequences.js +47 -12
- package/dist/commands/subscriptions.d.ts +2 -4
- package/dist/commands/subscriptions.js +297 -51
- package/dist/credential-storage/store.d.ts +10 -0
- package/dist/credential-storage/store.js +282 -0
- package/dist/credentials.d.ts +1 -3
- package/dist/credentials.js +3 -275
- package/dist/mailbox-fleet-output.js +11 -2
- package/dist/sequence-start-at.d.ts +7 -0
- package/dist/sequence-start-at.js +21 -0
- package/dist/sequences-brand-kit-command.d.ts +28 -0
- package/dist/sequences-brand-kit-command.js +83 -0
- package/dist/sequences-content-commands.d.ts +28 -0
- package/dist/sequences-content-commands.js +176 -0
- package/dist/sequences-newsletter-commands.d.ts +6 -0
- package/dist/sequences-newsletter-commands.js +108 -0
- package/dist/sequences-test-send-command.d.ts +3 -0
- package/dist/sequences-test-send-command.js +47 -0
- package/dist/workspace-placement-commands.js +3 -2
- package/node_modules/@oxygen/formula/dist/evaluate.js +2 -4
- package/node_modules/@oxygen/formula/dist/expression.d.ts +7 -5
- package/node_modules/@oxygen/formula/dist/expression.js +26 -4
- package/node_modules/@oxygen/formula/dist/formula-functions.d.ts +6 -0
- package/node_modules/@oxygen/formula/dist/formula-functions.js +55 -0
- package/node_modules/@oxygen/shared/dist/billing.d.ts +2 -2
- package/node_modules/@oxygen/shared/dist/billing.js +5 -7
- package/node_modules/@oxygen/shared/dist/bulk-email-pacing.d.ts +105 -0
- package/node_modules/@oxygen/shared/dist/bulk-email-pacing.js +125 -0
- package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +29 -0
- package/node_modules/@oxygen/shared/dist/capability-discovery.js +236 -18
- package/node_modules/@oxygen/shared/dist/clay-migration-auth-state.d.ts +7 -1
- package/node_modules/@oxygen/shared/dist/clay-migration-auth-state.js +6 -5
- package/node_modules/@oxygen/shared/dist/contracts/browser-operations.js +1 -0
- package/node_modules/@oxygen/shared/dist/contracts/clay-migration.d.ts +40 -1
- package/node_modules/@oxygen/shared/dist/contracts/clay-migration.js +60 -6
- package/node_modules/@oxygen/shared/dist/contracts/copilot-attachment-read.d.ts +24 -0
- package/node_modules/@oxygen/shared/dist/contracts/copilot-attachment-read.js +7 -0
- package/node_modules/@oxygen/shared/dist/contracts/customer-operations.js +2 -1
- package/node_modules/@oxygen/shared/dist/contracts/teammates.js +6 -1
- package/node_modules/@oxygen/shared/dist/copilot-journeys.generated.js +1 -1
- package/node_modules/@oxygen/shared/dist/copilot-playbooks.generated.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/copilot-playbooks.generated.js +2 -2
- package/node_modules/@oxygen/shared/dist/email-brand-kit.d.ts +108 -0
- package/node_modules/@oxygen/shared/dist/email-brand-kit.js +214 -0
- package/node_modules/@oxygen/shared/dist/email-classification-scope.d.ts +35 -0
- package/node_modules/@oxygen/shared/dist/email-classification-scope.js +40 -0
- package/node_modules/@oxygen/shared/dist/email-delivery.d.ts +10 -0
- package/node_modules/@oxygen/shared/dist/email-delivery.js +14 -0
- package/node_modules/@oxygen/shared/dist/email-documents.d.ts +61 -0
- package/node_modules/@oxygen/shared/dist/email-documents.js +143 -0
- package/node_modules/@oxygen/shared/dist/email-dsn.js +52 -10
- package/node_modules/@oxygen/shared/dist/email-html-sanitize.d.ts +23 -0
- package/node_modules/@oxygen/shared/dist/email-html-sanitize.js +96 -0
- package/node_modules/@oxygen/shared/dist/email-subscriptions.d.ts +63 -1
- package/node_modules/@oxygen/shared/dist/email-subscriptions.js +149 -1
- package/node_modules/@oxygen/shared/dist/email-unsubscribe-token.d.ts +41 -2
- package/node_modules/@oxygen/shared/dist/email-unsubscribe-token.js +50 -1
- package/node_modules/@oxygen/shared/dist/native-chat.d.ts +9 -0
- package/node_modules/@oxygen/shared/dist/native-chat.js +12 -1
- package/node_modules/@oxygen/shared/dist/newsletter-analytics.d.ts +90 -0
- package/node_modules/@oxygen/shared/dist/newsletter-analytics.js +28 -0
- package/node_modules/@oxygen/shared/dist/newsletter-test-send.d.ts +20 -0
- package/node_modules/@oxygen/shared/dist/newsletter-test-send.js +46 -0
- package/node_modules/@oxygen/shared/dist/object-storage.d.ts +11 -0
- package/node_modules/@oxygen/shared/dist/object-storage.js +12 -0
- package/node_modules/@oxygen/shared/dist/onboarding-research.d.ts +9 -2
- package/node_modules/@oxygen/shared/dist/onboarding-research.js +9 -2
- package/node_modules/@oxygen/shared/dist/plan-band.d.ts +9 -0
- package/node_modules/@oxygen/shared/dist/plan-band.js +17 -0
- package/node_modules/@oxygen/shared/dist/plan-capabilities.d.ts +4 -2
- package/node_modules/@oxygen/shared/dist/plan-capabilities.js +12 -1
- package/node_modules/@oxygen/shared/dist/plan-limits-view.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/plan-limits-view.js +3 -0
- package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +5 -0
- package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +5 -0
- package/node_modules/@oxygen/shared/dist/product-analytics-events.d.ts +29 -0
- package/node_modules/@oxygen/shared/dist/product-analytics-events.js +29 -0
- package/node_modules/@oxygen/shared/dist/recipes.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/recipes.js +13 -0
- package/node_modules/@oxygen/shared/dist/sending-domain-faults.d.ts +21 -0
- package/node_modules/@oxygen/shared/dist/sending-domain-faults.js +53 -0
- package/node_modules/@oxygen/shared/dist/sending-domain-rollout.d.ts +30 -0
- package/node_modules/@oxygen/shared/dist/sending-domain-rollout.js +75 -0
- package/node_modules/@oxygen/shared/dist/sequence-failures.d.ts +10 -1
- package/node_modules/@oxygen/shared/dist/sequence-failures.js +68 -6
- package/node_modules/@oxygen/shared/dist/sequence-lifecycle.d.ts +34 -3
- package/node_modules/@oxygen/shared/dist/sequence-lifecycle.js +57 -4
- package/node_modules/@oxygen/shared/dist/sequence-template.d.ts +17 -0
- package/node_modules/@oxygen/shared/dist/sequence-template.js +0 -0
- package/node_modules/@oxygen/shared/dist/sequences.d.ts +41 -0
- package/node_modules/@oxygen/shared/dist/sequences.js +86 -4
- package/node_modules/@oxygen/shared/dist/ses-identity-policy.d.ts +19 -0
- package/node_modules/@oxygen/shared/dist/ses-identity-policy.js +54 -0
- package/node_modules/@oxygen/shared/dist/skill-play-routing.d.ts +22 -0
- package/node_modules/@oxygen/shared/dist/skill-play-routing.js +75 -0
- package/node_modules/@oxygen/shared/dist/skill-plays.generated.d.ts +5 -0
- package/node_modules/@oxygen/shared/dist/skill-plays.generated.js +269 -0
- package/node_modules/@oxygen/shared/dist/spend-safety.d.ts +7 -0
- package/node_modules/@oxygen/shared/dist/spend-safety.js +7 -0
- package/node_modules/@oxygen/shared/dist/teammates.js +2 -1
- package/node_modules/@oxygen/shared/dist/tool-call-arguments.d.ts +24 -0
- package/node_modules/@oxygen/shared/dist/tool-call-arguments.js +68 -0
- package/node_modules/@oxygen/shared/dist/user-capability-routing.js +15 -1
- package/node_modules/@oxygen/shared/dist/version.generated.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.generated.js +1 -1
- package/node_modules/@oxygen/shared/dist/workspace-event-catalog.js +2 -2
- package/node_modules/@oxygen/shared/dist/workspace-placement.d.ts +3 -0
- package/node_modules/@oxygen/shared/dist/workspace-placement.js +11 -0
- package/package.json +2 -2
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
// GENERATED by apps/web/scripts/generate-copilot-playbooks.ts from the play
|
|
2
|
+
// catalog (`skill`, `title`, `trigger_phrases` in apps/web/src/lib/agent-skill-plays.ts).
|
|
3
|
+
// Do not edit by hand — run `npm run skills:metadata -w @oxygen/web`.
|
|
4
|
+
export const SKILL_PLAY_TRIGGERS_GENERATED = [
|
|
5
|
+
{
|
|
6
|
+
skill: "oxygen-clay-migration",
|
|
7
|
+
slug: "migrate-from-clay",
|
|
8
|
+
phrases: [
|
|
9
|
+
"Migrate from Clay",
|
|
10
|
+
"Move my whole Clay workspace into Oxygen",
|
|
11
|
+
"Clay is too expensive — what's the switch cost?",
|
|
12
|
+
"Rebuild my Clay waterfalls here",
|
|
13
|
+
"Import a Clay CSV and re-enrich it",
|
|
14
|
+
"How do I replace Claygent with Oxygen?",
|
|
15
|
+
"Bring my Clay company list over and score it",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
skill: "oxygen-crm",
|
|
20
|
+
slug: "website-visitor-outreach",
|
|
21
|
+
phrases: [
|
|
22
|
+
"Turn de-anonymized website visitors into warm pipeline",
|
|
23
|
+
"People visit our website but never convert",
|
|
24
|
+
"Who is on my site right now — and can we contact them?",
|
|
25
|
+
"Which companies visited our website this week?",
|
|
26
|
+
"Turn website traffic into leads",
|
|
27
|
+
"Set up visitor de-anonymization",
|
|
28
|
+
"Connect RB2B to OXYGEN",
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
skill: "oxygen-diagnostics",
|
|
33
|
+
slug: "day-30-review",
|
|
34
|
+
phrases: [
|
|
35
|
+
"Day 30: review, scale, or kill",
|
|
36
|
+
"What worked this month and what did it cost?",
|
|
37
|
+
"Review my GTM runs and decide what to scale",
|
|
38
|
+
"Monthly review of sequences and spend",
|
|
39
|
+
"Should I kill or scale this play?",
|
|
40
|
+
"Where did my credits go this month?",
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
skill: "oxygen-email-infra",
|
|
45
|
+
slug: "email-infra-setup",
|
|
46
|
+
phrases: [
|
|
47
|
+
"Set up cold email infrastructure",
|
|
48
|
+
"Set up cold email infrastructure",
|
|
49
|
+
"I need sending domains and mailboxes for outbound",
|
|
50
|
+
"How do I send cold email without burning my domain?",
|
|
51
|
+
"Buy me some inboxes for a cold email campaign",
|
|
52
|
+
"Stand up a warmed mailbox pool for outreach",
|
|
53
|
+
"What do sending inboxes cost per month?",
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
skill: "oxygen-knowledge",
|
|
58
|
+
slug: "client-workspace-launch",
|
|
59
|
+
phrases: [
|
|
60
|
+
"Stand up a new client workspace",
|
|
61
|
+
"Onboard a new client into Oxygen",
|
|
62
|
+
"Set up a workspace for a new client",
|
|
63
|
+
"How do I run Oxygen for multiple clients?",
|
|
64
|
+
"Stand up a client account from scratch",
|
|
65
|
+
"Repeatable client onboarding for my agency",
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
skill: "oxygen-onboarding",
|
|
70
|
+
slug: "day-1-first-win",
|
|
71
|
+
phrases: [
|
|
72
|
+
"Day 1: from your offer to your warmest leads",
|
|
73
|
+
"I just signed up — what do I actually do with this?",
|
|
74
|
+
"Where do I start with Oxygen?",
|
|
75
|
+
"Who should I contact first?",
|
|
76
|
+
"Find my warmest leads",
|
|
77
|
+
"What should I do in my first session?",
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
skill: "oxygen-publishing",
|
|
82
|
+
slug: "founder-posting-system",
|
|
83
|
+
phrases: [
|
|
84
|
+
"A founder posting system grounded in your knowledge base",
|
|
85
|
+
"I should be posting on LinkedIn but never do",
|
|
86
|
+
"Draft LinkedIn posts in my voice",
|
|
87
|
+
"Plan my LinkedIn content for the week",
|
|
88
|
+
"Set up a content calendar",
|
|
89
|
+
"I can't post consistently — schedule my posts for me",
|
|
90
|
+
"Turn my company knowledge into LinkedIn posts",
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
skill: "oxygen-sequencer",
|
|
95
|
+
slug: "inbound-led-outbound",
|
|
96
|
+
phrases: [
|
|
97
|
+
"Inbound-led outbound: post engagers into a capped warm sequence",
|
|
98
|
+
"Turn the people who engage with my LinkedIn posts into pipeline",
|
|
99
|
+
"Who is engaging with my competitors' or my niche creators' posts?",
|
|
100
|
+
"Reach the people engaging with LinkedIn posts about my topic",
|
|
101
|
+
"Turn my LinkedIn connections and followers into pipeline",
|
|
102
|
+
"Turn my LinkedIn profile viewers into leads",
|
|
103
|
+
"I have no lead list. Where do I start on LinkedIn?",
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
skill: "oxygen-sequencer",
|
|
108
|
+
slug: "multichannel-top-tier",
|
|
109
|
+
phrases: [
|
|
110
|
+
"Email + LinkedIn for top-tier leads",
|
|
111
|
+
"Combine email and LinkedIn for our best accounts",
|
|
112
|
+
"Run a multichannel sequence for top-tier leads",
|
|
113
|
+
"Email plus a LinkedIn invite for high-fit accounts",
|
|
114
|
+
"LinkedIn first for warm leads, email as the fallback",
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
skill: "oxygen-sequencer",
|
|
119
|
+
slug: "outbound-pilot-50",
|
|
120
|
+
phrases: [
|
|
121
|
+
"Launch a 50-lead outbound pilot",
|
|
122
|
+
"I need outbound running this week",
|
|
123
|
+
"Build me a cold outreach pilot",
|
|
124
|
+
"Find 50 leads and draft first emails for me to review",
|
|
125
|
+
"I have no pipeline — start outbound",
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
skill: "oxygen-sequencer",
|
|
130
|
+
slug: "signal-outbound",
|
|
131
|
+
phrases: [
|
|
132
|
+
"Signal-based email outbound",
|
|
133
|
+
"Email companies that are hiring for this role",
|
|
134
|
+
"Reach people who just showed buying intent",
|
|
135
|
+
"Turn hiring signals into cold email",
|
|
136
|
+
"Email our website visitors and signups who fit",
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
skill: "oxygen-sequencer",
|
|
141
|
+
slug: "whole-tam-email",
|
|
142
|
+
phrases: [
|
|
143
|
+
"Whole-market cold email",
|
|
144
|
+
"Run cold email across our whole market",
|
|
145
|
+
"Set up evergreen cold email at full capacity",
|
|
146
|
+
"A/B test our cold email CTAs and subject lines",
|
|
147
|
+
"Re-contact the people who never replied",
|
|
148
|
+
"The pilot worked — how do I scale cold email?",
|
|
149
|
+
"Build a repeatable cold email system",
|
|
150
|
+
],
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
skill: "oxygen-signals",
|
|
154
|
+
slug: "daily-warm-lead-queue",
|
|
155
|
+
phrases: [
|
|
156
|
+
"A daily ranked queue of your warmest leads",
|
|
157
|
+
"Who should I reach out to today?",
|
|
158
|
+
"Give me one ranked list of my warmest leads every morning",
|
|
159
|
+
"Turn all my intent signals into a daily to-do list",
|
|
160
|
+
"Make Oxygen do something while I'm not looking",
|
|
161
|
+
"What should I set up in my first week?",
|
|
162
|
+
"Set up a weekly CRM cleanup routine",
|
|
163
|
+
],
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
skill: "oxygen-signals",
|
|
167
|
+
slug: "existing-network",
|
|
168
|
+
phrases: [
|
|
169
|
+
"Hand-written first messages to buyers already in your network",
|
|
170
|
+
"Work my network",
|
|
171
|
+
"Reactivate my connections",
|
|
172
|
+
"Message the buyers I'm already connected to",
|
|
173
|
+
"Write personal messages to my LinkedIn connections",
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
skill: "oxygen-signals",
|
|
178
|
+
slug: "new-connections",
|
|
179
|
+
phrases: [
|
|
180
|
+
"Message the buyers among your new connections",
|
|
181
|
+
"Follow up with my new LinkedIn connections",
|
|
182
|
+
"Message the people who just connected with me",
|
|
183
|
+
"Which of my new connections are buyers?",
|
|
184
|
+
"Start conversations with my recent connections",
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
skill: "oxygen-signals",
|
|
189
|
+
slug: "post-engagers",
|
|
190
|
+
phrases: [
|
|
191
|
+
"Start conversations with the buyers who engage with your posts",
|
|
192
|
+
"Reach the people who engage with my LinkedIn posts",
|
|
193
|
+
"Message the people who commented on my post",
|
|
194
|
+
"Who reacted to my post, and are they buyers?",
|
|
195
|
+
"Turn my post engagers into conversations",
|
|
196
|
+
],
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
skill: "oxygen-signals",
|
|
200
|
+
slug: "profile-viewers-and-followers",
|
|
201
|
+
phrases: [
|
|
202
|
+
"Invite the buyers who view your profile or follow you",
|
|
203
|
+
"Reach out to the people who viewed my LinkedIn profile",
|
|
204
|
+
"Turn my LinkedIn followers into conversations",
|
|
205
|
+
"Invite my followers who aren't connected yet",
|
|
206
|
+
"Who viewed my profile, and should I contact them?",
|
|
207
|
+
],
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
skill: "oxygen-sourcing",
|
|
211
|
+
slug: "icp-to-account-map",
|
|
212
|
+
phrases: [
|
|
213
|
+
"Turn your ICP into a scored account map",
|
|
214
|
+
"Turn my ICP into a list of target accounts",
|
|
215
|
+
"Find B2B SaaS accounts that match our ideal customer profile",
|
|
216
|
+
"Who should we actually be selling to?",
|
|
217
|
+
"Map my market and score the companies by fit",
|
|
218
|
+
"Pull the companies off this VC portfolio, partner directory or event page",
|
|
219
|
+
"I have a list of companies, which ones fit us best?",
|
|
220
|
+
],
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
skill: "oxygen-sourcing",
|
|
224
|
+
slug: "local-business-maps",
|
|
225
|
+
phrases: [
|
|
226
|
+
"Local businesses from Google Maps",
|
|
227
|
+
"Find local businesses in my cities",
|
|
228
|
+
"Get a list of clinics or restaurants by city",
|
|
229
|
+
"Pull businesses from Google Maps",
|
|
230
|
+
"Our buyers are local businesses with a physical location",
|
|
231
|
+
],
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
skill: "oxygen-sourcing",
|
|
235
|
+
slug: "lookalike-tam",
|
|
236
|
+
phrases: [
|
|
237
|
+
"Lookalike TAM",
|
|
238
|
+
"Find more companies like our best customers",
|
|
239
|
+
"Build a lookalike list from our customers",
|
|
240
|
+
"Who else looks like the customers we already have?",
|
|
241
|
+
"Use our customers as seeds to map our market",
|
|
242
|
+
],
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
skill: "oxygen-tables",
|
|
246
|
+
slug: "speed-to-lead",
|
|
247
|
+
phrases: [
|
|
248
|
+
"Answer inbound leads in minutes",
|
|
249
|
+
"New signups sit for days before anyone reaches out",
|
|
250
|
+
"Route my inbound leads into the CRM automatically",
|
|
251
|
+
"Answer trial signups the same day they arrive",
|
|
252
|
+
"Set up speed-to-lead for my demo requests",
|
|
253
|
+
"Enrich and follow up on form fills without me watching",
|
|
254
|
+
],
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
skill: "oxygen-unibox",
|
|
258
|
+
slug: "reply-to-meeting",
|
|
259
|
+
phrases: [
|
|
260
|
+
"Turn replies into booked meetings",
|
|
261
|
+
"I get replies but they never turn into meetings",
|
|
262
|
+
"Help me handle my inbound replies faster",
|
|
263
|
+
"Book more meetings from the replies I already have",
|
|
264
|
+
"Log booked calls in my CRM automatically",
|
|
265
|
+
"What do I do with 'circle back next quarter' replies?",
|
|
266
|
+
"Bring deferred leads back when they're ready",
|
|
267
|
+
],
|
|
268
|
+
},
|
|
269
|
+
];
|
|
@@ -158,6 +158,13 @@ export type CopilotApprovalFreeAllowance = {
|
|
|
158
158
|
* largest session allowance stays below the attended turn backstop above.
|
|
159
159
|
*/
|
|
160
160
|
export declare const COPILOT_APPROVAL_FREE_ALLOWANCE_BY_PLAN_BAND: Readonly<Record<PlanBand, CopilotApprovalFreeAllowance>>;
|
|
161
|
+
/**
|
|
162
|
+
* On every plan, an Oxygent call whose declared ceiling (`max_credits`, the
|
|
163
|
+
* maximum quote, never the estimate) is strictly BELOW this runs without an
|
|
164
|
+
* approval card (Philipp, 2026-10-21). It only adds to the per-call allowance
|
|
165
|
+
* above, never lowers one, and the per-session allowance still applies.
|
|
166
|
+
*/
|
|
167
|
+
export declare const OXYGENT_APPROVAL_FREE_BELOW_CREDITS = 100;
|
|
161
168
|
/** A plan size's approval-free Copilot allowance. */
|
|
162
169
|
export declare function copilotApprovalFreeAllowanceForBand(band: PlanBand): CopilotApprovalFreeAllowance;
|
|
163
170
|
export declare function resolveDefaultByokColumnRunMaxRows(tier: SpendSafetyPlanTier): number | null;
|
|
@@ -191,6 +191,13 @@ export const COPILOT_APPROVAL_FREE_ALLOWANCE_BY_PLAN_BAND = Object.freeze({
|
|
|
191
191
|
"999": Object.freeze({ perCallCredits: 300, perSessionCredits: 1_500 }),
|
|
192
192
|
"1999": Object.freeze({ perCallCredits: 500, perSessionCredits: 2_500 }),
|
|
193
193
|
});
|
|
194
|
+
/**
|
|
195
|
+
* On every plan, an Oxygent call whose declared ceiling (`max_credits`, the
|
|
196
|
+
* maximum quote, never the estimate) is strictly BELOW this runs without an
|
|
197
|
+
* approval card (Philipp, 2026-10-21). It only adds to the per-call allowance
|
|
198
|
+
* above, never lowers one, and the per-session allowance still applies.
|
|
199
|
+
*/
|
|
200
|
+
export const OXYGENT_APPROVAL_FREE_BELOW_CREDITS = 100;
|
|
194
201
|
/** A plan size's approval-free Copilot allowance. */
|
|
195
202
|
export function copilotApprovalFreeAllowanceForBand(band) {
|
|
196
203
|
return COPILOT_APPROVAL_FREE_ALLOWANCE_BY_PLAN_BAND[band];
|
|
@@ -169,5 +169,6 @@ export function teammateSlugFromName(name) {
|
|
|
169
169
|
*/
|
|
170
170
|
export const TEAMMATE_STARTER_INSTRUCTIONS = [
|
|
171
171
|
"You are an Oxygent on the team. Do the job your profile and the person give you, and hand work that is another Oxygent's job to them.",
|
|
172
|
-
"Read whatever you need from the workspace; ask before anything that writes, sends or spends.",
|
|
172
|
+
"Read whatever you need from the workspace; ask before anything that writes, sends or spends 100 credits or more.",
|
|
173
|
+
"A paid step quoted under 100 credits, such as a sample lead list, runs without asking, rows it writes included: say what it cost in one plain line.",
|
|
173
174
|
].join("\n");
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One reader for a model tool call's `arguments` string, shared by the Copilot
|
|
3
|
+
* (packages/copilot model-output.ts) and the Agents runtime host
|
|
4
|
+
* (apps/worker agent-cycle.ts) so an Oxygent run and a Copilot turn accept and
|
|
5
|
+
* refuse exactly the same payloads.
|
|
6
|
+
*
|
|
7
|
+
* Only a plain JSON object is an argument set. A complete object followed only
|
|
8
|
+
* by surplus closing brackets is read as the object: measured on the medium tier
|
|
9
|
+
* (System 1, s1-knowledge-update-page, 2026-10-21), a capability_run with a
|
|
10
|
+
* nested page body closed with one `}` too many four times in one turn, each
|
|
11
|
+
* `Unexpected non-whitespace character after JSON`. The object before the
|
|
12
|
+
* surplus is exactly what the model wrote; any other trailing text still fails.
|
|
13
|
+
*/
|
|
14
|
+
export type ToolCallArgumentsRead = {
|
|
15
|
+
ok: true;
|
|
16
|
+
value: Record<string, unknown>;
|
|
17
|
+
} | {
|
|
18
|
+
ok: false;
|
|
19
|
+
/** The parse error, or why a parsed value is not an argument set. */
|
|
20
|
+
error: string;
|
|
21
|
+
/** The text around the break, from the FULL payload (an echoed head may end before it). */
|
|
22
|
+
near?: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function readToolCallArgumentObject(raw: string): ToolCallArgumentsRead;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const NOT_AN_OBJECT = "Tool-call arguments must be a JSON object.";
|
|
2
|
+
export function readToolCallArgumentObject(raw) {
|
|
3
|
+
let parsed;
|
|
4
|
+
let error;
|
|
5
|
+
try {
|
|
6
|
+
parsed = JSON.parse(raw);
|
|
7
|
+
}
|
|
8
|
+
catch (caught) {
|
|
9
|
+
error = caught instanceof Error ? caught.message : String(caught);
|
|
10
|
+
const trimmed = withoutSurplusClosers(raw);
|
|
11
|
+
if (trimmed !== null) {
|
|
12
|
+
try {
|
|
13
|
+
parsed = JSON.parse(trimmed);
|
|
14
|
+
error = undefined;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
parsed = undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// An ARRAY and a bare string both survive JSON.parse; only a plain object is a
|
|
22
|
+
// valid argument set, so the check is on the shape rather than on the throw.
|
|
23
|
+
if (error === undefined && parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
24
|
+
return { ok: true, value: parsed };
|
|
25
|
+
}
|
|
26
|
+
const message = error ?? NOT_AN_OBJECT;
|
|
27
|
+
const position = Number(/at position (\d+)/.exec(message)?.[1]);
|
|
28
|
+
return {
|
|
29
|
+
ok: false,
|
|
30
|
+
error: message,
|
|
31
|
+
...(Number.isFinite(position)
|
|
32
|
+
? { near: raw.slice(Math.max(0, position - 60), position + 20) }
|
|
33
|
+
: {}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** The payload up to its first complete top-level object when only closers follow, else null. */
|
|
37
|
+
function withoutSurplusClosers(raw) {
|
|
38
|
+
let depth = 0;
|
|
39
|
+
let inString = false;
|
|
40
|
+
let escaped = false;
|
|
41
|
+
const start = raw.search(/\S/);
|
|
42
|
+
if (start < 0 || raw[start] !== "{")
|
|
43
|
+
return null;
|
|
44
|
+
for (let index = start; index < raw.length; index += 1) {
|
|
45
|
+
const char = raw[index];
|
|
46
|
+
if (inString) {
|
|
47
|
+
if (escaped)
|
|
48
|
+
escaped = false;
|
|
49
|
+
else if (char === "\\")
|
|
50
|
+
escaped = true;
|
|
51
|
+
else if (char === '"')
|
|
52
|
+
inString = false;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (char === '"')
|
|
56
|
+
inString = true;
|
|
57
|
+
else if (char === "{" || char === "[")
|
|
58
|
+
depth += 1;
|
|
59
|
+
else if (char === "}" || char === "]") {
|
|
60
|
+
depth -= 1;
|
|
61
|
+
if (depth === 0) {
|
|
62
|
+
const rest = raw.slice(index + 1);
|
|
63
|
+
return rest.trim() !== "" && /^[\s}\]]*$/.test(rest) ? raw.slice(0, index + 1) : null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getCapabilityRoute, getCapabilityRouteMatch, inferCapabilityRoute, } from "./capability-discovery.js";
|
|
2
|
+
const GROUP_CHAT_CHANNEL_PATTERN = /\b(?:whatsapp|teams|slack|telegram|linkedin|discord|signal|sms|e ?mail|inbox|unibox)\b/;
|
|
2
3
|
/** A null route has no command to hydrate yet. Keep recovery bounded and executable. */
|
|
3
4
|
export function capabilityDiscoveryRecovery(query, surface) {
|
|
4
5
|
if (surface === "mcp") {
|
|
@@ -166,6 +167,19 @@ export function inferUserCapabilityRoute(query) {
|
|
|
166
167
|
exactMcpCall: { tool: "oxygen_agent_session_list", arguments: { slug: "workspace" } },
|
|
167
168
|
};
|
|
168
169
|
}
|
|
170
|
+
if (/\b(?:files?|attachments?|documents?|uploads?)\b/.test(normalized)
|
|
171
|
+
&& /\b(?:group\s+(?:chats?|conversations?)|team\s+(?:chats?|conversations?))\b/.test(normalized)
|
|
172
|
+
&& !GROUP_CHAT_CHANNEL_PATTERN.test(normalized)
|
|
173
|
+
&& !/\b(?:support|external)\b/.test(normalized)) {
|
|
174
|
+
const route = getCapabilityRouteMatch("agents");
|
|
175
|
+
if (route) {
|
|
176
|
+
const tools = ["oxygen_oxygents_group", "oxygen_oxygents_group_message", "oxygen_copilot_attachments", "oxygen_copilot_get"];
|
|
177
|
+
const commands = ["oxygents group", "copilot attach", "copilot attachments", "oxygents group-message", "copilot get"];
|
|
178
|
+
return { ...route, recommendedTools: tools, recommendedCommands: commands,
|
|
179
|
+
card: { ...route.card, endpointSections: [...route.card.endpointSections, "copilot"], gatewayTools: tools, gatewayCommands: commands,
|
|
180
|
+
execution: "A group_id is its Copilot session id. Upload your file with oxygen copilot attach <group_id> <path>, list its ready ids with copilot attachments (oxygen_copilot_attachments), then send attachment_ids with oxygents group-message (oxygen_oxygents_group_message). Read messages and bound files with copilot get (oxygen_copilot_get). Existing uploader, session, readiness and group-access checks apply. A message mentioning only a person goes to them; Oxygent answers are billed turns." } };
|
|
181
|
+
}
|
|
182
|
+
}
|
|
169
183
|
const oxygents = oxygentsRoute(normalized);
|
|
170
184
|
if (oxygents)
|
|
171
185
|
return oxygents;
|
|
@@ -335,7 +349,7 @@ const OXYGENT_GROUP_VERBS = [
|
|
|
335
349
|
*/
|
|
336
350
|
function oxygentsRoute(normalized) {
|
|
337
351
|
const groupChat = /\bgroup chats?\b/.test(normalized)
|
|
338
|
-
&&
|
|
352
|
+
&& !GROUP_CHAT_CHANNEL_PATTERN.test(normalized);
|
|
339
353
|
const nativeTeammate = /^\s*teammates?\s*$/.test(normalized)
|
|
340
354
|
|| (/\bteammates?\b/.test(normalized) && /\b(?:routines?|schedul\w*|private chat)\b/.test(normalized)
|
|
341
355
|
&& !/\b(?:invite|membership|permissions?|roles?|human|colleague|coworker|slack|teams|whatsapp)\b/.test(normalized));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const OXYGEN_BUILD_VERSION = "1.1014.
|
|
1
|
+
export declare const OXYGEN_BUILD_VERSION = "1.1014.1763";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// GENERATED by scripts/ci/version-stamp.mjs from VERSION + git history. Do not edit; do not commit.
|
|
2
|
-
export const OXYGEN_BUILD_VERSION = "1.1014.
|
|
2
|
+
export const OXYGEN_BUILD_VERSION = "1.1014.1763";
|
|
@@ -144,10 +144,10 @@ function sequenceActivityDescription(key, label) {
|
|
|
144
144
|
}
|
|
145
145
|
function crmActivityDescription(key, label) {
|
|
146
146
|
if (key === "email_bounced") {
|
|
147
|
-
return "An email-bounce activity was added to a CRM record timeline
|
|
147
|
+
return "An email-bounce activity was added to a CRM record timeline by anything except a workflow. Use the Sequencer preset for an outreach enrollment's own bounce outcome.";
|
|
148
148
|
}
|
|
149
149
|
if (key === "meeting_booked") {
|
|
150
|
-
return "A meeting-booked activity was added to a CRM record timeline
|
|
150
|
+
return "A meeting-booked activity was added to a CRM record timeline by anything except a workflow (a workflow-logged meeting, such as from the Cal.com router, never fires it). Use the Sequencer preset for an outreach enrollment's own meeting outcome.";
|
|
151
151
|
}
|
|
152
152
|
if (key === "placement_changed") {
|
|
153
153
|
return "Inbox placement for a sender domain at one receiver provider changed (inbox rate drop or Gmail Primary to Promotions). A workspace Signal with no CRM record; placement never pauses a sender.";
|
|
@@ -20,6 +20,7 @@ export type StaffPlacementGrant = {
|
|
|
20
20
|
source_environment: "dev" | "prod";
|
|
21
21
|
receiver_environment: "dev" | "prod";
|
|
22
22
|
receiver_workspace_id: string;
|
|
23
|
+
allow_daily_limit_override?: true;
|
|
23
24
|
};
|
|
24
25
|
export type WorkspacePlacementProbe = {
|
|
25
26
|
id: string;
|
|
@@ -51,6 +52,8 @@ export declare function workspacePlacementId(value: unknown): value is string;
|
|
|
51
52
|
export declare function readWorkspacePlacementVariants(value: unknown): WorkspacePlacementVariant[];
|
|
52
53
|
export declare function readWorkspacePlacementMailboxIds(value: unknown): string[];
|
|
53
54
|
export declare function workspacePlacementPlanHash(plan: Omit<WorkspacePlacementPlan, "plan_hash">): string;
|
|
55
|
+
/** Exact staff approval can exempt one diagnostic per sender from daily quotas. */
|
|
56
|
+
export declare function workspacePlacementDailyLimitOverride(plan: Pick<WorkspacePlacementPlan, "receiver_scope" | "staff" | "probes" | "message_count">): boolean;
|
|
54
57
|
export declare function buildWorkspacePlacementPlan(input: {
|
|
55
58
|
requestId: string;
|
|
56
59
|
organizationId: string;
|
|
@@ -48,6 +48,15 @@ function canonicalPlacementValue(value) {
|
|
|
48
48
|
export function workspacePlacementPlanHash(plan) {
|
|
49
49
|
return createHash("sha256").update(JSON.stringify(plan.receiver_scope === "staff" ? canonicalPlacementValue(plan) : plan)).digest("hex");
|
|
50
50
|
}
|
|
51
|
+
/** Exact staff approval can exempt one diagnostic per sender from daily quotas. */
|
|
52
|
+
export function workspacePlacementDailyLimitOverride(plan) {
|
|
53
|
+
if (plan.receiver_scope !== "staff" || plan.staff?.allow_daily_limit_override !== true || typeof plan.staff.actor_id !== "string" || !plan.staff.actor_id.trim()
|
|
54
|
+
|| !Array.isArray(plan.probes) || plan.probes.length < 1 || plan.probes.length > 50 || plan.message_count !== plan.probes.length
|
|
55
|
+
|| plan.probes.some(p => typeof p?.sender?.address !== "string" || !workspacePlacementId(p.sender.id)))
|
|
56
|
+
return false;
|
|
57
|
+
return new Set(plan.probes.map(p => p.sender.address.toLowerCase())).size === plan.probes.length
|
|
58
|
+
&& new Set(plan.probes.map(p => `${p.sender.environment}:${p.sender.organization_id}:${p.sender.id}`)).size === plan.probes.length;
|
|
59
|
+
}
|
|
51
60
|
export function buildWorkspacePlacementPlan(input) {
|
|
52
61
|
if (!workspacePlacementId(input.requestId) || !workspacePlacementId(input.organizationId))
|
|
53
62
|
invalid("The workspace test request is invalid.");
|
|
@@ -95,6 +104,8 @@ export function buildWorkspacePlacementPlan(input) {
|
|
|
95
104
|
...(input.network ? { receiver_scope: "network" } : input.staff ? { receiver_scope: "staff", staff: input.staff } : {}), billing_mode: "internal", credits: 0, allow_paused_probe: input.allowPausedProbe,
|
|
96
105
|
...(input.renderedAt ? { rendered_at: input.renderedAt } : {}), ...(input.rendering ? { rendering: input.rendering } : {}),
|
|
97
106
|
probes, excluded_self_sends: excluded, message_count: probes.length };
|
|
107
|
+
if (input.staff?.allow_daily_limit_override && !workspacePlacementDailyLimitOverride(plan))
|
|
108
|
+
invalid("Daily-limit overrides allow only one diagnostic email per sender in the approved staff test.");
|
|
98
109
|
return { ...plan, plan_hash: workspacePlacementPlanHash(plan) };
|
|
99
110
|
}
|
|
100
111
|
export function googleWorkspacePlacement(labels, messageId, observedAt) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxygen-agent/cli",
|
|
3
|
-
"version": "1.1014.
|
|
3
|
+
"version": "1.1014.1763",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@opentelemetry/resources": "2.10.0",
|
|
43
43
|
"@opentelemetry/sdk-trace-base": "2.10.0",
|
|
44
44
|
"commander": "14.0.3",
|
|
45
|
-
"esbuild": "0.
|
|
45
|
+
"esbuild": "0.28.2",
|
|
46
46
|
"read-excel-file": "6.0.3",
|
|
47
47
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
48
48
|
"yaml": "2.9.0",
|