@oxygen-agent/cli 1.347.1 → 1.353.2
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/index.js +20 -123
- 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/shared/dist/workspace-agents.d.ts +4 -2
- package/node_modules/@oxygen/shared/dist/workspace-agents.js +18 -13
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1518,38 +1518,6 @@ function buildCrmAutomationAuditPath(options) {
|
|
|
1518
1518
|
const query = params.toString();
|
|
1519
1519
|
return query ? `/api/cli/crm/automation/audit?${query}` : "/api/cli/crm/automation/audit";
|
|
1520
1520
|
}
|
|
1521
|
-
function buildCrmListCreateBody(slug, options) {
|
|
1522
|
-
const body = {
|
|
1523
|
-
slug,
|
|
1524
|
-
base_object: options.base,
|
|
1525
|
-
kind: options.kind,
|
|
1526
|
-
mode: resolveLiveDryRunMode(options),
|
|
1527
|
-
};
|
|
1528
|
-
if (options.displayName)
|
|
1529
|
-
body.display_name = options.displayName;
|
|
1530
|
-
if (options.project)
|
|
1531
|
-
body.project = options.project;
|
|
1532
|
-
if (options.filterJson)
|
|
1533
|
-
body.filter = parseJsonObject(options.filterJson);
|
|
1534
|
-
return body;
|
|
1535
|
-
}
|
|
1536
|
-
function buildCrmListEntryBody(object, rowId, options) {
|
|
1537
|
-
return {
|
|
1538
|
-
object,
|
|
1539
|
-
row_id: rowId,
|
|
1540
|
-
mode: resolveLiveDryRunMode(options),
|
|
1541
|
-
};
|
|
1542
|
-
}
|
|
1543
|
-
function buildCrmListMembersPath(list, options) {
|
|
1544
|
-
const params = new URLSearchParams();
|
|
1545
|
-
if (options.limit)
|
|
1546
|
-
params.set("limit", options.limit);
|
|
1547
|
-
if (options.cursor)
|
|
1548
|
-
params.set("cursor", options.cursor);
|
|
1549
|
-
const query = params.toString();
|
|
1550
|
-
const base = `/api/cli/crm/lists/${encodeURIComponent(list)}/members`;
|
|
1551
|
-
return query ? `${base}?${query}` : base;
|
|
1552
|
-
}
|
|
1553
1521
|
function parseCrmIdentityOption(value) {
|
|
1554
1522
|
const separator = value.indexOf("=");
|
|
1555
1523
|
if (separator <= 0 || separator === value.length - 1) {
|
|
@@ -3168,68 +3136,6 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
3168
3136
|
.option("--json", "Print a JSON envelope.")
|
|
3169
3137
|
.action(async (options) => {
|
|
3170
3138
|
await handleAsyncAction("crm signals leads-today", options, () => requestOxygen(buildCrmLeadsTodayPath(options)));
|
|
3171
|
-
})))
|
|
3172
|
-
.addCommand(new Command("lists")
|
|
3173
|
-
.description("Static and dynamic CRM lists over companies, people, deals, and custom objects.")
|
|
3174
|
-
.addCommand(new Command("create")
|
|
3175
|
-
.description("Create a static or dynamic CRM list. Defaults to dry-run.")
|
|
3176
|
-
.argument("<slug>", "List slug, such as vip_accounts.")
|
|
3177
|
-
.requiredOption("--base <object>", "Base CRM object slug the list draws from, such as people.")
|
|
3178
|
-
.requiredOption("--kind <kind>", "List kind: static (materialized) or dynamic (filter-computed).")
|
|
3179
|
-
.option("--filter-json <json>", "Dynamic-list filter as a JSON FilterTree object.")
|
|
3180
|
-
.option("--display-name <name>", "Human-friendly list name.")
|
|
3181
|
-
.option("--project <project>", "Project id or slug for the backing list table.")
|
|
3182
|
-
.option("--dry-run", "Preview the list without creating it.")
|
|
3183
|
-
.option("--live", "Create the list. Default is dry-run.")
|
|
3184
|
-
.option("--json", "Print a JSON envelope.")
|
|
3185
|
-
.action(async (slug, options) => {
|
|
3186
|
-
await handleAsyncAction("crm lists create", options, () => requestOxygen("/api/cli/crm/lists", {
|
|
3187
|
-
method: "POST",
|
|
3188
|
-
body: buildCrmListCreateBody(slug, options),
|
|
3189
|
-
}));
|
|
3190
|
-
}))
|
|
3191
|
-
.addCommand(new Command("add")
|
|
3192
|
-
.description("Add a record to a static CRM list. Defaults to dry-run.")
|
|
3193
|
-
.argument("<list>", "List slug.")
|
|
3194
|
-
.argument("<object>", "Base CRM object slug, such as people.")
|
|
3195
|
-
.argument("<row_id>", "Base record row id.")
|
|
3196
|
-
.option("--dry-run", "Preview the add without writing it.")
|
|
3197
|
-
.option("--live", "Write the membership. Default is dry-run.")
|
|
3198
|
-
.option("--json", "Print a JSON envelope.")
|
|
3199
|
-
.action(async (list, object, rowId, options) => {
|
|
3200
|
-
await handleAsyncAction("crm lists add", options, () => requestOxygen(`/api/cli/crm/lists/${encodeURIComponent(list)}/entries`, {
|
|
3201
|
-
method: "POST",
|
|
3202
|
-
body: buildCrmListEntryBody(object, rowId, options),
|
|
3203
|
-
}));
|
|
3204
|
-
}))
|
|
3205
|
-
.addCommand(new Command("remove")
|
|
3206
|
-
.description("Remove a record from a static CRM list. Defaults to dry-run.")
|
|
3207
|
-
.argument("<list>", "List slug.")
|
|
3208
|
-
.argument("<object>", "Base CRM object slug, such as people.")
|
|
3209
|
-
.argument("<row_id>", "Base record row id.")
|
|
3210
|
-
.option("--dry-run", "Preview the removal without writing it.")
|
|
3211
|
-
.option("--live", "Tombstone the membership. Default is dry-run.")
|
|
3212
|
-
.option("--json", "Print a JSON envelope.")
|
|
3213
|
-
.action(async (list, object, rowId, options) => {
|
|
3214
|
-
await handleAsyncAction("crm lists remove", options, () => requestOxygen(`/api/cli/crm/lists/${encodeURIComponent(list)}/entries`, {
|
|
3215
|
-
method: "DELETE",
|
|
3216
|
-
body: buildCrmListEntryBody(object, rowId, options),
|
|
3217
|
-
}));
|
|
3218
|
-
}))
|
|
3219
|
-
.addCommand(new Command("members")
|
|
3220
|
-
.description("List a CRM list's members (the audience for sequence enrollment).")
|
|
3221
|
-
.argument("<list>", "List slug.")
|
|
3222
|
-
.option("--limit <limit>", "Maximum members to return.")
|
|
3223
|
-
.option("--cursor <cursor>", "Pagination cursor from a previous page.")
|
|
3224
|
-
.option("--json", "Print a JSON envelope.")
|
|
3225
|
-
.action(async (list, options) => {
|
|
3226
|
-
await handleAsyncAction("crm lists members", options, () => requestOxygen(buildCrmListMembersPath(list, options)));
|
|
3227
|
-
}))
|
|
3228
|
-
.addCommand(new Command("ls")
|
|
3229
|
-
.description("List every configured CRM list.")
|
|
3230
|
-
.option("--json", "Print a JSON envelope.")
|
|
3231
|
-
.action(async (options) => {
|
|
3232
|
-
await handleAsyncAction("crm lists ls", options, () => requestOxygen("/api/cli/crm/lists"));
|
|
3233
3139
|
})))
|
|
3234
3140
|
.addCommand(new Command("automation")
|
|
3235
3141
|
.description("Arm / disarm standing CRM automation templates and read the audit trail.")
|
|
@@ -6136,7 +6042,7 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
6136
6042
|
.option("--from <iso>", "Only include ledger events at or after this ISO timestamp.")
|
|
6137
6043
|
.option("--to <iso>", "Only include ledger events at or before this ISO timestamp.")
|
|
6138
6044
|
.option("--limit <n>", "Maximum grouped rows to return. Defaults to 100.")
|
|
6139
|
-
.option("--group-by <keys>", "Comma-separated grouping keys. Defaults to provider,source.")
|
|
6045
|
+
.option("--group-by <keys>", "Comma-separated grouping keys (day, type, category, provider, source, tool, model, run, workspace). Defaults to provider,source.")
|
|
6140
6046
|
.option("--type <type>", "Filter by transaction type, such as reserve, capture, release, grant, or byok_usage.")
|
|
6141
6047
|
.option("--category <category>", "Filter by transaction category, such as managed_enrichment, managed_ai, byok, subscription, or admin.")
|
|
6142
6048
|
.option("--provider <provider>", "Filter by provider id.")
|
|
@@ -6666,14 +6572,14 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
6666
6572
|
return data;
|
|
6667
6573
|
});
|
|
6668
6574
|
}));
|
|
6669
|
-
//
|
|
6670
|
-
//
|
|
6671
|
-
//
|
|
6672
|
-
//
|
|
6673
|
-
// configures the
|
|
6575
|
+
// The Agents primitive's roster surface (ADR 0011): governed workspace agents
|
|
6576
|
+
// that run inside the workspace as approval-gated, observable runs. Lists only
|
|
6577
|
+
// shipped agents — no placeholders; user-defined custom agents arrive with the
|
|
6578
|
+
// unified runtime envelope (create/update land then). (Distinct from
|
|
6579
|
+
// `oxygen knowledge agent`, which configures the AI Knowledge Agent itself.)
|
|
6674
6580
|
program
|
|
6675
6581
|
.command("agent")
|
|
6676
|
-
.description("
|
|
6582
|
+
.description("Agents: your workspace agents (AI Sales Agent, AI Meeting Notetaker, AI Knowledge Agent) that work inside your workspace as approval-gated runs. List them, inspect run history, and enable or disable each one; each agent's `configCommand` (e.g. `oxygen inbox reply-agent set` for the AI Sales Agent) tunes its behavior. Web: /agents.")
|
|
6677
6583
|
.addCommand(new Command("list")
|
|
6678
6584
|
.description("List the built-in specialist agents with their enabled state and recent run history.")
|
|
6679
6585
|
.option("--json", "Print a JSON envelope.")
|
|
@@ -7582,30 +7488,27 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
7582
7488
|
});
|
|
7583
7489
|
})));
|
|
7584
7490
|
program.addCommand(new Command("followers")
|
|
7585
|
-
.description("Read a LinkedIn account's followers into a Clay-like workspace table
|
|
7491
|
+
.description("Read a LinkedIn account's followers into a Clay-like workspace table you can enrich, qualify, and enroll from. Imports run as a slow, durable background drip under a dedicated conservative read budget — they never burst and never starve the sequencer's own reads.")
|
|
7586
7492
|
.addCommand(new Command("import")
|
|
7587
|
-
.description("Start (or re-arm) a followers import. Followers drip into a workspace table + the deduped mirror over many ticks
|
|
7493
|
+
.description("Start (or re-arm) a followers import. Followers drip into a workspace table + the deduped mirror over many ticks; poll `followers status` to watch them accrue. The import keeps itself fresh by periodically re-walking followers in the background (new followers dedupe in). No messages are sent and no Oxygen credits are charged.")
|
|
7588
7494
|
.option("--account <ref>", "Sender account to import (sender id, connection id, or Unipile account id). Omit to import every active LinkedIn account.")
|
|
7589
7495
|
.option("--table <ref>", "Existing workspace table (id or slug) to import into. Omit to create or reuse a 'LinkedIn Followers' table.")
|
|
7590
|
-
.option("--list <slug>", "Enrollable CRM static list slug to bridge new followers into. Omit for the default 'linkedin-followers' list.")
|
|
7591
7496
|
.option("--json", "Print a JSON envelope.")
|
|
7592
7497
|
.action(async (options) => {
|
|
7593
7498
|
await handleAsyncAction("followers import", options, () => {
|
|
7594
7499
|
const account = readOption(options.account);
|
|
7595
7500
|
const table = readOption(options.table);
|
|
7596
|
-
const list = readOption(options.list);
|
|
7597
7501
|
return requestOxygen("/api/cli/linkedin/followers/import", {
|
|
7598
7502
|
method: "POST",
|
|
7599
7503
|
body: {
|
|
7600
7504
|
...(account ? { account } : {}),
|
|
7601
7505
|
...(table ? { table } : {}),
|
|
7602
|
-
...(list ? { list } : {}),
|
|
7603
7506
|
},
|
|
7604
7507
|
});
|
|
7605
7508
|
});
|
|
7606
7509
|
}))
|
|
7607
7510
|
.addCommand(new Command("status")
|
|
7608
|
-
.description("Show followers-import progress (per-sender drip status, followers ingested, last error) plus a preview of the followers table
|
|
7511
|
+
.description("Show followers-import progress (per-sender drip status, followers ingested, last error) plus a preview of the followers table and a deep-link to open it.")
|
|
7609
7512
|
.option("--account <ref>", "Scope to one sender account (sender id, connection id, or Unipile account id).")
|
|
7610
7513
|
.option("--json", "Print a JSON envelope.")
|
|
7611
7514
|
.action(async (options) => {
|
|
@@ -7619,30 +7522,27 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
7619
7522
|
});
|
|
7620
7523
|
})));
|
|
7621
7524
|
program.addCommand(new Command("viewers")
|
|
7622
|
-
.description("Read the named LinkedIn 'who viewed my profile' (WVMP) viewers into a Clay-like workspace table
|
|
7525
|
+
.description("Read the named LinkedIn 'who viewed my profile' (WVMP) viewers into a Clay-like workspace table. Imports run as a slow, durable background drip under a dedicated conservative read budget. LinkedIn hides anonymous/private viewers, so the table is always a partial sample.")
|
|
7623
7526
|
.addCommand(new Command("import")
|
|
7624
|
-
.description("Start (or re-arm) a durable profile-viewers (WVMP) import. Named viewers drip into a workspace table + the deduped mirror (view_count / last_viewed_at accumulate) over many ticks
|
|
7527
|
+
.description("Start (or re-arm) a durable profile-viewers (WVMP) import. Named viewers drip into a workspace table + the deduped mirror (view_count / last_viewed_at accumulate) over many ticks; poll `viewers status` to watch them accrue. No messages are sent and no Oxygen credits are charged.")
|
|
7625
7528
|
.option("--account <ref>", "Sender account to import (sender id, connection id, or Unipile account id). Omit to import every active LinkedIn account.")
|
|
7626
7529
|
.option("--table <ref>", "Existing workspace table (id or slug) to import into. Omit to create or reuse a 'LinkedIn Profile Viewers' table.")
|
|
7627
|
-
.option("--list <slug>", "Enrollable CRM static list slug to bridge new viewers into. Omit for the default 'linkedin-profile-viewers' list.")
|
|
7628
7530
|
.option("--json", "Print a JSON envelope.")
|
|
7629
7531
|
.action(async (options) => {
|
|
7630
7532
|
await handleAsyncAction("viewers import", options, () => {
|
|
7631
7533
|
const account = readOption(options.account);
|
|
7632
7534
|
const table = readOption(options.table);
|
|
7633
|
-
const list = readOption(options.list);
|
|
7634
7535
|
return requestOxygen("/api/cli/linkedin/viewers/import", {
|
|
7635
7536
|
method: "POST",
|
|
7636
7537
|
body: {
|
|
7637
7538
|
...(account ? { account } : {}),
|
|
7638
7539
|
...(table ? { table } : {}),
|
|
7639
|
-
...(list ? { list } : {}),
|
|
7640
7540
|
},
|
|
7641
7541
|
});
|
|
7642
7542
|
});
|
|
7643
7543
|
}))
|
|
7644
7544
|
.addCommand(new Command("status")
|
|
7645
|
-
.description("Show durable profile-viewers (WVMP) import progress (per-sender drip status, viewers ingested, last error, the preserved privacy ceiling note) plus a preview of the viewers table
|
|
7545
|
+
.description("Show durable profile-viewers (WVMP) import progress (per-sender drip status, viewers ingested, last error, the preserved privacy ceiling note) plus a preview of the viewers table and a deep-link to open it.")
|
|
7646
7546
|
.option("--account <ref>", "Scope to one sender account (sender id, connection id, or Unipile account id).")
|
|
7647
7547
|
.option("--json", "Print a JSON envelope.")
|
|
7648
7548
|
.action(async (options) => {
|
|
@@ -7757,11 +7657,10 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
7757
7657
|
});
|
|
7758
7658
|
})));
|
|
7759
7659
|
program.addCommand(new Command("engagement")
|
|
7760
|
-
.description("Harvest a LinkedIn post's engagers (reactors + commenters) into an enrollable
|
|
7660
|
+
.description("Harvest a LinkedIn post's engagers (reactors + commenters) into an enrollable workspace table. The harvest runs as a slow, durable background drip under a dedicated conservative read budget — it never bursts and never starves the sequencer's own reads.")
|
|
7761
7661
|
.addCommand(new Command("harvest")
|
|
7762
|
-
.description("Start (or re-arm) a harvest of a post's engagers into a
|
|
7662
|
+
.description("Start (or re-arm) a harvest of a post's engagers into a workspace table you can enroll into a sequence. Engagers drip into the table over many ticks; poll `engagement status` to watch it fill. No messages are sent. Cookieless harvests spend Oxygen credits per scraper page and require --max-credits.")
|
|
7763
7663
|
.requiredOption("--post <social_id_or_url>", "Composite post social_id from `oxygen posts get` (NOT the activity URN), or the public LinkedIn post URL for cookieless.")
|
|
7764
|
-
.requiredOption("--list <slug>", "CRM static list slug to fill (created or reused over the people object).")
|
|
7765
7664
|
.option("--source <source>", "cookieless|unipile. Defaults to cookieless when a public post URL is supplied.")
|
|
7766
7665
|
.option("--post-url <url>", "Public LinkedIn post URL for cookieless harvesting when --post is a social id.")
|
|
7767
7666
|
.option("--max-credits <credits>", "Required for cookieless harvesting; caps managed scraper spend for this armed run.")
|
|
@@ -7773,7 +7672,6 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
7773
7672
|
.action(async (options) => {
|
|
7774
7673
|
await handleAsyncAction("engagement harvest", options, () => {
|
|
7775
7674
|
const post = readOption(options.post);
|
|
7776
|
-
const list = readOption(options.list);
|
|
7777
7675
|
const account = readOption(options.account);
|
|
7778
7676
|
const source = readOption(options.source);
|
|
7779
7677
|
const postUrl = readOption(options.postUrl);
|
|
@@ -7782,7 +7680,6 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
7782
7680
|
method: "POST",
|
|
7783
7681
|
body: {
|
|
7784
7682
|
...(post ? { post } : {}),
|
|
7785
|
-
...(list ? { list } : {}),
|
|
7786
7683
|
...(source ? { source } : {}),
|
|
7787
7684
|
...(postUrl ? { post_url: postUrl } : {}),
|
|
7788
7685
|
...(maxCredits !== undefined ? { max_credits: maxCredits } : {}),
|
|
@@ -7796,7 +7693,7 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
7796
7693
|
});
|
|
7797
7694
|
}))
|
|
7798
7695
|
.addCommand(new Command("status")
|
|
7799
|
-
.description("Show an engagement harvest's progress (drip status, engagers ingested, last error) plus the
|
|
7696
|
+
.description("Show an engagement harvest's progress (drip status, engagers ingested, last error) plus the workspace table it fills and a preview of harvested engagers.")
|
|
7800
7697
|
.option("--account <ref>", "Scope to one sender account (sender id, connection id, or Unipile account id).")
|
|
7801
7698
|
.option("--post <social_id>", "Scope to one harvested post.")
|
|
7802
7699
|
.option("--json", "Print a JSON envelope.")
|
|
@@ -8545,7 +8442,7 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
8545
8442
|
});
|
|
8546
8443
|
})))
|
|
8547
8444
|
.addCommand(new Command("reply-agent")
|
|
8548
|
-
.description("The draft-only AI reply agent (the 'AI Sales Agent'): auto-classifies + auto-drafts replies into the review queue. It NEVER auto-sends.")
|
|
8445
|
+
.description("The draft-only AI reply agent (the 'AI Sales Agent'): auto-classifies + auto-drafts replies into the review queue. It NEVER auto-sends. Roster + run history: `oxygen agent get inbox-reply-drafts`; web home: /agents/inbox-reply-drafts.")
|
|
8549
8446
|
.addCommand(new Command("get")
|
|
8550
8447
|
.description("Show the reply-agent config.")
|
|
8551
8448
|
.option("--json", "Print a JSON envelope.")
|
|
@@ -8553,11 +8450,11 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
8553
8450
|
await handleAsyncAction("inbox reply-agent get", options, () => requestOxygen("/api/cli/inbox/reply-agent"));
|
|
8554
8451
|
}))
|
|
8555
8452
|
.addCommand(new Command("set")
|
|
8556
|
-
.description("Configure the reply agent (enable, persona/tone, targets). It drafts into the queue; a human approves+sends.")
|
|
8453
|
+
.description("Configure the reply agent (enable, persona/tone, targets). It drafts into the queue; a human approves+sends. Configuring is free (no credits); once enabled, each draft the agent writes consumes credits.")
|
|
8557
8454
|
.option("--enabled", "Enable the agent.")
|
|
8558
8455
|
.option("--disabled", "Disable the agent.")
|
|
8559
|
-
.option("--persona <text>", "Who the agent
|
|
8560
|
-
.option("--tone <text>", "
|
|
8456
|
+
.option("--persona <text>", "Who the agent writes as — drafts open in this voice. Richest results name role + company + what you sell, e.g. \"Jonas, founder of Acme (dev-tools for CI caching)\".")
|
|
8457
|
+
.option("--tone <text>", "How drafts should read, e.g. \"warm, concise, low-pressure\".")
|
|
8561
8458
|
.option("--instructions <text>", "Extra drafting instructions.")
|
|
8562
8459
|
.option("--signature <text>", "Signature appended to drafts.")
|
|
8563
8460
|
.option("--target-statuses <keys>", "Comma-separated statuses to draft for (empty = all draftable).")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const OXYGEN_VERSION = "1.
|
|
1
|
+
export const OXYGEN_VERSION = "1.353.2";
|
|
2
2
|
// The GLOBAL CLI compatibility floor: the oldest CLI allowed to call any
|
|
3
3
|
// operational route. Raising it hard-rejects every older CLI from the entire
|
|
4
4
|
// product, so it obeys one law, enforced by scripts/ci/cli-min-version-gate.mjs:
|
|
@@ -8,10 +8,12 @@ export type WorkspaceAgentSlug = "inbox-reply-drafts" | "meeting-notetaker" | "k
|
|
|
8
8
|
export type WorkspaceAgentDeepLinkKind = "inbox_reply_agent" | "notetaker" | "knowledge_agent";
|
|
9
9
|
/** A pure, serializable descriptor for one Workspace Agent specialist. */
|
|
10
10
|
export type WorkspaceAgentDescriptor = {
|
|
11
|
-
/** Stable identifier used across CLI/MCP/API. */
|
|
11
|
+
/** Stable identifier used across CLI/MCP/API. Never derived from the title. */
|
|
12
12
|
slug: WorkspaceAgentSlug;
|
|
13
|
-
/**
|
|
13
|
+
/** Persona-style display name ("AI Sales Agent"). Display-only — the slug is the contract. */
|
|
14
14
|
title: string;
|
|
15
|
+
/** One honest job line shown under the persona name ("Drafts inbox replies — never sends without your approval."). */
|
|
16
|
+
subtitle: string;
|
|
15
17
|
/** One outcome-framed sentence: what the specialist produces for the user. */
|
|
16
18
|
description: string;
|
|
17
19
|
/** The OXYGEN OS primitive this specialist writes into. */
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
// The
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
1
|
+
// The Agents primitive's roster (ADR 0011): the governed registry of OXYGEN's
|
|
2
|
+
// built-in workspace agents. Still deliberately a *computed* registry — each
|
|
3
|
+
// entry is a product-defined agent that ships as an approval-gated, observable
|
|
4
|
+
// behavior elsewhere in the product, surfaced under /agents and `oxygen agent`.
|
|
5
|
+
// Agents are governed workspace workers: the runtime envelope (approval posture,
|
|
6
|
+
// credit budgets, run observability) is platform-enforced, never agent-optional.
|
|
7
|
+
// User-defined custom agents are ratified (ADR 0011) but arrive with the unified
|
|
8
|
+
// runtime envelope in a later phase — until then there is no create/define verb,
|
|
9
|
+
// and there are never placeholder rows: the roster lists only agents that are
|
|
10
|
+
// actually implemented today. CRM-hygiene, deliverability, and any other roadmap
|
|
11
|
+
// agent stay OUT until they ship — the no-placeholder-surface rule.
|
|
10
12
|
//
|
|
11
13
|
// This module is a dependency-free leaf (pure descriptors + types) so it can live
|
|
12
|
-
// in @oxygen/shared without importing tenant-db: the actual per-
|
|
14
|
+
// in @oxygen/shared without importing tenant-db: the actual per-agent wiring
|
|
13
15
|
// (config read/write, run history, deep-links) lives in the web layer's
|
|
14
16
|
// agent-registry, which composes these descriptors with the existing helpers.
|
|
15
17
|
/**
|
|
@@ -20,7 +22,8 @@
|
|
|
20
22
|
export const WORKSPACE_AGENT_ROSTER = [
|
|
21
23
|
{
|
|
22
24
|
slug: "inbox-reply-drafts",
|
|
23
|
-
title: "
|
|
25
|
+
title: "AI Sales Agent",
|
|
26
|
+
subtitle: "Drafts inbox replies — never sends without your approval.",
|
|
24
27
|
description: "Drafts replies to inbound prospect and customer messages so you can review, edit, and approve them before anything sends.",
|
|
25
28
|
owningPrimitive: "Messages",
|
|
26
29
|
configCommand: "oxygen inbox reply-agent",
|
|
@@ -31,7 +34,8 @@ export const WORKSPACE_AGENT_ROSTER = [
|
|
|
31
34
|
},
|
|
32
35
|
{
|
|
33
36
|
slug: "meeting-notetaker",
|
|
34
|
-
title: "Meeting
|
|
37
|
+
title: "AI Meeting Notetaker",
|
|
38
|
+
subtitle: "Joins scoped meetings to record, transcribe, and file notes.",
|
|
35
39
|
description: "Auto-joins meetings in its configured scope to record, transcribe, and file meeting notes onto the matching CRM records.",
|
|
36
40
|
owningPrimitive: "Records",
|
|
37
41
|
configCommand: "oxygen notetaker setup",
|
|
@@ -42,7 +46,8 @@ export const WORKSPACE_AGENT_ROSTER = [
|
|
|
42
46
|
},
|
|
43
47
|
{
|
|
44
48
|
slug: "knowledge-synthesis",
|
|
45
|
-
title: "Knowledge
|
|
49
|
+
title: "AI Knowledge Agent",
|
|
50
|
+
subtitle: "Distills outreach and meeting learnings into workspace knowledge.",
|
|
46
51
|
description: "Distills captured outreach and meeting learnings into workspace knowledge pages on the schedule and daily credit cap you set.",
|
|
47
52
|
owningPrimitive: "Knowledge Graph",
|
|
48
53
|
configCommand: "oxygen knowledge agent",
|