@oxygen-agent/cli 1.615.0 → 1.618.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 +178 -17
- package/node_modules/@oxygen/shared/dist/capability-discovery.js +8 -3
- package/node_modules/@oxygen/shared/dist/crm-activity-events.d.ts +127 -0
- package/node_modules/@oxygen/shared/dist/crm-activity-events.js +40 -0
- package/node_modules/@oxygen/shared/dist/crm-reply-events.d.ts +43 -0
- package/node_modules/@oxygen/shared/dist/crm-reply-events.js +110 -0
- 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/sequence-crm-events.d.ts +1 -1
- 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 +3 -3
- package/node_modules/@oxygen/shared/dist/workspace-agents.js +5 -5
- package/node_modules/@oxygen/shared/dist/workspace-event-catalog.d.ts +22 -0
- package/node_modules/@oxygen/shared/dist/workspace-event-catalog.js +144 -0
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -28,6 +28,8 @@ import { doctorAgentSkills, getAgentSkill, installAgentSkills, listAgentSkills,
|
|
|
28
28
|
import { resolveCliBinaryName } from "./runtime.js";
|
|
29
29
|
import { updateCli } from "./update.js";
|
|
30
30
|
import { isRecord, readErrorMessage, readOption } from "./util.js";
|
|
31
|
+
const AGENT_MODEL_POLICY_HELP = "Model policy JSON: level low (Fast), medium (Balanced, default), or high (Max); credential_mode managed or organization_byok.";
|
|
32
|
+
const AGENT_TOOL_POLICY_HELP = "Tool policy JSON. Effects: read, internal_write, paid, external_write. Ask-before-changes preset: {\"mode\":\"scoped\",\"rules\":[{\"decision\":\"allow\",\"effect\":\"read\"},{\"decision\":\"ask\",\"effect\":\"internal_write\"},{\"decision\":\"ask\",\"effect\":\"paid\"},{\"decision\":\"ask\",\"effect\":\"external_write\"}]}. Full mode requires --confirm-full-access.";
|
|
31
33
|
/**
|
|
32
34
|
* Build the registry patch body. An omitted field keeps its stored value; an
|
|
33
35
|
* explicit null clears it — so a `--clear-*` flag must send null, and a flag the
|
|
@@ -555,6 +557,97 @@ function writeBulkWorkflowResults(data, okVerb) {
|
|
|
555
557
|
process.stdout.write(`${counts.join(", ")}\n`);
|
|
556
558
|
writeWorkflowActionTail(record);
|
|
557
559
|
}
|
|
560
|
+
const WORKSPACE_EVENTS_HUMAN_LIMIT = 20;
|
|
561
|
+
function workspaceEventFilterText(event) {
|
|
562
|
+
const filters = Array.isArray(event.filters) ? event.filters : [];
|
|
563
|
+
if (filters.length === 0)
|
|
564
|
+
return "all payloads";
|
|
565
|
+
return filters
|
|
566
|
+
.filter(isRecord)
|
|
567
|
+
.map((filter) => {
|
|
568
|
+
const path = typeof filter.path === "string" ? filter.path : "?";
|
|
569
|
+
const op = typeof filter.op === "string" ? filter.op : "?";
|
|
570
|
+
return filter.value === undefined ? `${path} ${op}` : `${path} ${op} ${String(filter.value)}`;
|
|
571
|
+
})
|
|
572
|
+
.join(" · ");
|
|
573
|
+
}
|
|
574
|
+
function formatWorkspaceEventsList(data) {
|
|
575
|
+
const events = Array.isArray(data.events) ? data.events.filter(isRecord) : [];
|
|
576
|
+
const total = typeof data.total === "number" ? data.total : events.length;
|
|
577
|
+
const availableTotal = typeof data.available_total === "number" ? data.available_total : total;
|
|
578
|
+
const builtin = typeof data.builtin_count === "number"
|
|
579
|
+
? data.builtin_count
|
|
580
|
+
: events.filter((event) => event.kind === "builtin").length;
|
|
581
|
+
const integrations = typeof data.integration_count === "number"
|
|
582
|
+
? data.integration_count
|
|
583
|
+
: events.filter((event) => event.kind === "integration").length;
|
|
584
|
+
const existing = typeof data.existing_count === "number"
|
|
585
|
+
? data.existing_count
|
|
586
|
+
: events.filter((event) => event.kind === "existing").length;
|
|
587
|
+
const query = isRecord(data.query) ? data.query : {};
|
|
588
|
+
const queryParts = ["search", "source", "kind"].flatMap((key) => typeof query[key] === "string" ? [`${key}=${query[key]}`] : []);
|
|
589
|
+
const lines = [
|
|
590
|
+
total === availableTotal
|
|
591
|
+
? `${total} workspace event${total === 1 ? "" : "s"} available`
|
|
592
|
+
: `${total} of ${availableTotal} workspace events matched`,
|
|
593
|
+
`${builtin} curated preset${builtin === 1 ? "" : "s"} · ${integrations} connected · ${existing} existing`,
|
|
594
|
+
];
|
|
595
|
+
if (queryParts.length > 0)
|
|
596
|
+
lines.push(`Filters: ${queryParts.join(" · ")}`);
|
|
597
|
+
lines.push("");
|
|
598
|
+
if (events.length === 0) {
|
|
599
|
+
lines.push("No workspace events matched. Try a broader --search, or remove --source/--kind.");
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
for (const event of events.slice(0, WORKSPACE_EVENTS_HUMAN_LIMIT)) {
|
|
603
|
+
const label = typeof event.label === "string"
|
|
604
|
+
? event.label
|
|
605
|
+
: typeof event.event === "string" ? event.event : "Workspace event";
|
|
606
|
+
const kind = typeof event.kind === "string" ? event.kind : "event";
|
|
607
|
+
lines.push(`- ${label} [${kind}]`);
|
|
608
|
+
if (typeof event.catalogId === "string")
|
|
609
|
+
lines.push(` catalog: ${event.catalogId}`);
|
|
610
|
+
const source = typeof event.source === "string" ? event.source : "?";
|
|
611
|
+
const eventName = typeof event.event === "string" ? event.event : "?";
|
|
612
|
+
lines.push(` trigger: ${source}.${eventName} · ${workspaceEventFilterText(event)}`);
|
|
613
|
+
if (typeof event.description === "string")
|
|
614
|
+
lines.push(` ${event.description}`);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
if (events.length > WORKSPACE_EVENTS_HUMAN_LIMIT) {
|
|
618
|
+
lines.push("", `Showing ${WORKSPACE_EVENTS_HUMAN_LIMIT} of ${events.length}; narrow with --search, --source, or --kind. Use --json for every match.`);
|
|
619
|
+
}
|
|
620
|
+
lines.push("", "Inspect one: oxygen workflows events get <catalog-id>");
|
|
621
|
+
if (typeof data.web_url === "string")
|
|
622
|
+
lines.push(data.web_url);
|
|
623
|
+
return `${lines.join("\n")}\n`;
|
|
624
|
+
}
|
|
625
|
+
function formatWorkspaceEventDetail(data) {
|
|
626
|
+
const event = isRecord(data.event) ? data.event : null;
|
|
627
|
+
if (!event)
|
|
628
|
+
return `${JSON.stringify(data, null, 2)}\n`;
|
|
629
|
+
const label = typeof event.label === "string" ? event.label : String(event.event ?? "Workspace event");
|
|
630
|
+
const lines = [label];
|
|
631
|
+
if (typeof event.catalogId === "string")
|
|
632
|
+
lines.push(`Catalog: ${event.catalogId}`);
|
|
633
|
+
if (typeof event.group === "string")
|
|
634
|
+
lines.push(`Group: ${event.group}`);
|
|
635
|
+
if (typeof event.kind === "string")
|
|
636
|
+
lines.push(`Kind: ${event.kind}`);
|
|
637
|
+
if (typeof event.description === "string")
|
|
638
|
+
lines.push(`When it fires: ${event.description}`);
|
|
639
|
+
if (isRecord(data.trigger)) {
|
|
640
|
+
lines.push("", "Trigger:", ...JSON.stringify(data.trigger, null, 2).split("\n").map((line) => ` ${line}`));
|
|
641
|
+
}
|
|
642
|
+
const payloadFields = Array.isArray(event.payloadFields)
|
|
643
|
+
? event.payloadFields.filter((field) => typeof field === "string")
|
|
644
|
+
: [];
|
|
645
|
+
if (payloadFields.length > 0)
|
|
646
|
+
lines.push("", `Payload fields: ${payloadFields.join(", ")}`);
|
|
647
|
+
if (typeof data.web_url === "string")
|
|
648
|
+
lines.push("", data.web_url);
|
|
649
|
+
return `${lines.join("\n")}\n`;
|
|
650
|
+
}
|
|
558
651
|
// Paid live runs and ambiguous external-effect retries are refused server-side with typed safety-gate errors
|
|
559
652
|
// (max_credits_required, approval_required, spend_cap_required,
|
|
560
653
|
// spend_cap_too_low). Surface each as a one-line stderr hint with the concrete
|
|
@@ -8154,7 +8247,7 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
8154
8247
|
// `oxygen knowledge agent`, which configures the AI Knowledge Agent itself.)
|
|
8155
8248
|
program
|
|
8156
8249
|
.command("agent")
|
|
8157
|
-
.description("Agents: the programmable Workspace Agent
|
|
8250
|
+
.description("Agents: the programmable Workspace Agent, custom Agents, and built-in specialists. Publish versioned instructions and policies, start durable chats/runs, inspect every event, and control approvals. Web: /agents.")
|
|
8158
8251
|
.addCommand(new Command("list")
|
|
8159
8252
|
.description("List the Workspace Agent and built-in specialists with state and recent run history.")
|
|
8160
8253
|
.option("--json", "Print a JSON envelope.")
|
|
@@ -8204,8 +8297,8 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
8204
8297
|
.description("Publish an immutable version (reconfigure) for a runtime agent: the Workspace Agent or a custom agent.")
|
|
8205
8298
|
.argument("<slug>", "workspace, or a custom agent slug (from `oxygen agent create`).")
|
|
8206
8299
|
.requiredOption("--instructions <text>", "Workspace Agent instructions for this version.")
|
|
8207
|
-
.option("--model-policy-json <json>",
|
|
8208
|
-
.option("--tool-policy-json <json>",
|
|
8300
|
+
.option("--model-policy-json <json>", AGENT_MODEL_POLICY_HELP)
|
|
8301
|
+
.option("--tool-policy-json <json>", AGENT_TOOL_POLICY_HELP)
|
|
8209
8302
|
.option("--context-policy-json <json>", "Context policy JSON: on_demand or prefetch, optional resolve_args and file_ids.")
|
|
8210
8303
|
.option("--skills <csv>", "Comma-separated product skill slugs snapshotted into this immutable version.")
|
|
8211
8304
|
.option("--sandbox-policy-json <json>", "Sandbox policy JSON.")
|
|
@@ -8228,13 +8321,13 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
8228
8321
|
}));
|
|
8229
8322
|
}))
|
|
8230
8323
|
.addCommand(new Command("create")
|
|
8231
|
-
.description("Create a custom
|
|
8324
|
+
.description("Create a custom Agent and publish its first immutable version. This internal configuration write starts no chat/run and spends no credits.")
|
|
8232
8325
|
.argument("<slug>", "User-minted agent slug: a lowercase letter then letters, digits, or hyphens (2-49 chars).")
|
|
8233
8326
|
.requiredOption("--name <name>", "Display name for the agent.")
|
|
8234
8327
|
.requiredOption("--instructions <text>", "Durable standing instructions for the first immutable version.")
|
|
8235
8328
|
.option("--description <text>", "Optional one-line description of the agent's job.")
|
|
8236
|
-
.option("--model-policy-json <json>",
|
|
8237
|
-
.option("--tool-policy-json <json>",
|
|
8329
|
+
.option("--model-policy-json <json>", AGENT_MODEL_POLICY_HELP)
|
|
8330
|
+
.option("--tool-policy-json <json>", AGENT_TOOL_POLICY_HELP)
|
|
8238
8331
|
.option("--context-policy-json <json>", "Context policy JSON: on_demand or prefetch, optional resolve_args and file_ids.")
|
|
8239
8332
|
.option("--skills <csv>", "Comma-separated product skill slugs snapshotted into this immutable version.")
|
|
8240
8333
|
.option("--sandbox-policy-json <json>", "Sandbox policy JSON.")
|
|
@@ -8273,8 +8366,8 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
8273
8366
|
await handleAsyncAction("agent delete", options, () => requestOxygen(`/api/cli/agent/${encodeURIComponent(slug)}`, { method: "DELETE" }));
|
|
8274
8367
|
}))
|
|
8275
8368
|
.addCommand(new Command("run")
|
|
8276
|
-
.description("Start a durable Workspace Agent
|
|
8277
|
-
.argument("<slug>", "
|
|
8369
|
+
.description("Start a durable chat/run for the Workspace Agent or a custom Agent on the Fly worker.")
|
|
8370
|
+
.argument("<slug>", "workspace, or a custom Agent slug from `oxygen agent custom`.")
|
|
8278
8371
|
.option("--goal <text>", "Natural-language goal.")
|
|
8279
8372
|
.option("--input-json <json>", "Structured run input instead of --goal.")
|
|
8280
8373
|
.option("--idempotency-key <key>", "Deduplicate retries of the same source event.")
|
|
@@ -8305,8 +8398,8 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
8305
8398
|
});
|
|
8306
8399
|
}))
|
|
8307
8400
|
.addCommand(new Command("run-get")
|
|
8308
|
-
.description("Inspect one Workspace Agent run and its append-only event ledger.")
|
|
8309
|
-
.argument("<slug>", "
|
|
8401
|
+
.description("Inspect one Workspace or custom Agent run and its append-only event ledger.")
|
|
8402
|
+
.argument("<slug>", "workspace, or a custom Agent slug from `oxygen agent custom`.")
|
|
8310
8403
|
.argument("<run-id>", "Agent run id.")
|
|
8311
8404
|
.option("--after-seq <n>", "Return events after this sequence number.")
|
|
8312
8405
|
.option("--json", "Print a JSON envelope.")
|
|
@@ -8320,16 +8413,16 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
8320
8413
|
});
|
|
8321
8414
|
}))
|
|
8322
8415
|
.addCommand(new Command("cancel")
|
|
8323
|
-
.description("Request cancellation of an active Workspace Agent run.")
|
|
8324
|
-
.argument("<slug>", "
|
|
8416
|
+
.description("Request cancellation of an active Workspace or custom Agent run.")
|
|
8417
|
+
.argument("<slug>", "workspace, or a custom Agent slug from `oxygen agent custom`.")
|
|
8325
8418
|
.argument("<run-id>", "Agent run id.")
|
|
8326
8419
|
.option("--json", "Print a JSON envelope.")
|
|
8327
8420
|
.action(async (slug, runId, options) => {
|
|
8328
8421
|
await handleAsyncAction("agent run cancel", options, () => requestOxygen(`/api/cli/agent/${encodeURIComponent(slug)}/runs/${encodeURIComponent(runId)}/cancel`, { method: "POST" }));
|
|
8329
8422
|
}))
|
|
8330
8423
|
.addCommand(new Command("approval-decide")
|
|
8331
|
-
.description("Approve or reject one pending Workspace Agent tool call, then resume its durable run.")
|
|
8332
|
-
.argument("<slug>", "
|
|
8424
|
+
.description("Approve or reject one pending Workspace or custom Agent tool call, then resume its durable run.")
|
|
8425
|
+
.argument("<slug>", "workspace, or a custom Agent slug from `oxygen agent custom`.")
|
|
8333
8426
|
.argument("<run-id>", "Agent run id.")
|
|
8334
8427
|
.argument("<approval-id>", "Approval id from the run event ledger.")
|
|
8335
8428
|
.requiredOption("--decision <approved|rejected>", "Decision.")
|
|
@@ -9072,11 +9165,11 @@ fixed scan; watermark_cursor starts a later bounded replay. Consumers must retai
|
|
|
9072
9165
|
}));
|
|
9073
9166
|
program
|
|
9074
9167
|
.command("integrations")
|
|
9075
|
-
.description("Integration
|
|
9168
|
+
.description("Integration connections and raw provider-webhook subscriptions. Trigger-ready workspace events live under `workflows events list`. Hypertide mailbox exports use `mailboxes import --from hypertide`, not this group.")
|
|
9076
9169
|
.addCommand(new Command("events")
|
|
9077
|
-
.description("
|
|
9170
|
+
.description("Inspect raw provider event definitions and manage subscriptions that feed workflows; use `workflows events list` for the trigger-ready workspace catalog.")
|
|
9078
9171
|
.addCommand(new Command("list")
|
|
9079
|
-
.description("List
|
|
9172
|
+
.description("List raw provider event definitions and this org's enabled subscriptions. To choose a workflow trigger, use `oxygen workflows events list`.")
|
|
9080
9173
|
.option("--source <source>", "Filter by event source, such as hubspot or composio.gmail.")
|
|
9081
9174
|
.option("--event <event>", "Filter by event type, such as contact.created.")
|
|
9082
9175
|
.option("--toolkit <id>", "Filter by toolkit / integration id, such as gmail.")
|
|
@@ -13585,6 +13678,74 @@ Run completion:
|
|
|
13585
13678
|
})))
|
|
13586
13679
|
.addCommand(new Command("events")
|
|
13587
13680
|
.description("Workflow event trigger utilities.")
|
|
13681
|
+
.addCommand(new Command("list")
|
|
13682
|
+
.description("Search and filter every app-native and connected event this workspace can use as a workflow trigger.")
|
|
13683
|
+
.option("--search <text>", "Match labels, catalog ids, descriptions, endpoints, filters, or payload fields.")
|
|
13684
|
+
.option("--source <source>", "Match one event source exactly, such as sequencer or crm.")
|
|
13685
|
+
.option("--kind <kind>", "Match builtin, integration, or existing events.")
|
|
13686
|
+
.option("--json", "Print a JSON envelope.")
|
|
13687
|
+
.addHelpText("after", `
|
|
13688
|
+
Cost: 0 credits · read-only.
|
|
13689
|
+
|
|
13690
|
+
Use each returned source, event, and filters array together. Curated presets can
|
|
13691
|
+
share one underlying source/event pair and differ only by filters.
|
|
13692
|
+
|
|
13693
|
+
This is the trigger-ready workspace catalog. oxygen integrations events list
|
|
13694
|
+
instead shows raw provider webhook definitions and the subscriptions that feed
|
|
13695
|
+
connected entries into this catalog.
|
|
13696
|
+
|
|
13697
|
+
Kinds:
|
|
13698
|
+
builtin Curated Oxygen preset with labels, filters, and payload fields.
|
|
13699
|
+
integration Event from an active workspace integration subscription.
|
|
13700
|
+
existing Raw source/event retained from an existing workflow trigger;
|
|
13701
|
+
no preset filter is required.
|
|
13702
|
+
|
|
13703
|
+
Example trigger:
|
|
13704
|
+
{"type":"event","source":"crm","event":"activity_created",
|
|
13705
|
+
"filters":[{"path":"activity_type","op":"eq","value":"meeting_booked"}]}
|
|
13706
|
+
|
|
13707
|
+
Full trigger schema: oxygen workflows schema --subject trigger --json
|
|
13708
|
+
`)
|
|
13709
|
+
.action(async (options) => {
|
|
13710
|
+
try {
|
|
13711
|
+
const query = new URLSearchParams();
|
|
13712
|
+
const search = readOption(options.search);
|
|
13713
|
+
const source = readOption(options.source);
|
|
13714
|
+
const kind = readOption(options.kind);
|
|
13715
|
+
if (search)
|
|
13716
|
+
query.set("search", search);
|
|
13717
|
+
if (source)
|
|
13718
|
+
query.set("source", source);
|
|
13719
|
+
if (kind)
|
|
13720
|
+
query.set("kind", kind);
|
|
13721
|
+
const suffix = query.toString() ? `?${query.toString()}` : "";
|
|
13722
|
+
const data = await requestOxygen(`/api/cli/workflows/events/catalog${suffix}`);
|
|
13723
|
+
if (options.json)
|
|
13724
|
+
writeJson(success("workflows events list", data));
|
|
13725
|
+
else
|
|
13726
|
+
process.stdout.write(formatWorkspaceEventsList(data));
|
|
13727
|
+
}
|
|
13728
|
+
catch (error) {
|
|
13729
|
+
emitCliFailure("workflows events list", error);
|
|
13730
|
+
}
|
|
13731
|
+
}))
|
|
13732
|
+
.addCommand(new Command("get")
|
|
13733
|
+
.description("Get one curated workspace-event preset and its ready-to-copy trigger object.")
|
|
13734
|
+
.argument("<catalog_id>", "Exact catalog id returned by workflows events list.")
|
|
13735
|
+
.option("--json", "Print a JSON envelope.")
|
|
13736
|
+
.addHelpText("after", "\nCost: 0 credits · read-only. Integration/existing entries have no curated catalog id; filter them with workflows events list.\n")
|
|
13737
|
+
.action(async (catalogId, options) => {
|
|
13738
|
+
try {
|
|
13739
|
+
const data = await requestOxygen(`/api/cli/workflows/events/catalog?catalog_id=${encodeURIComponent(catalogId)}`);
|
|
13740
|
+
if (options.json)
|
|
13741
|
+
writeJson(success("workflows events get", data));
|
|
13742
|
+
else
|
|
13743
|
+
process.stdout.write(formatWorkspaceEventDetail(data));
|
|
13744
|
+
}
|
|
13745
|
+
catch (error) {
|
|
13746
|
+
emitCliFailure("workflows events get", error);
|
|
13747
|
+
}
|
|
13748
|
+
}))
|
|
13588
13749
|
.addCommand(new Command("emit")
|
|
13589
13750
|
.description("Emit a normalized workflow event and enqueue matching event-triggered workflows.")
|
|
13590
13751
|
.requiredOption("--source <source>", "Event source, such as instantly, calendar, hubspot, or oxygen.notetaker.")
|
|
@@ -151,11 +151,16 @@ export const OXYGEN_CAPABILITY_ROUTES = [
|
|
|
151
151
|
notFor: "Canonical CRM truth, message cadence, or an off-platform spreadsheet runtime.",
|
|
152
152
|
execution: "Create and run work in hosted OXYGEN Tables; validate a small sample before bounded paid runs.",
|
|
153
153
|
posture: "mixed",
|
|
154
|
-
gatewayTools: ["oxygen_tables_create", "oxygen_columns_add", "oxygen_enrich_column_preview"],
|
|
155
|
-
gatewayCommands: ["tables create", "columns add", "enrich-column preview"],
|
|
154
|
+
gatewayTools: ["oxygen_tables_create", "oxygen_columns_add", "oxygen_enrich_column_preview", "oxygen_tables_link_bulk"],
|
|
155
|
+
gatewayCommands: ["tables create", "columns add", "enrich-column preview", "tables link"],
|
|
156
156
|
skills: ["oxygen-gtm", "oxygen-table-tidy", "oxygen-diagnostics", "oxygen-clay-migration"],
|
|
157
157
|
endpointSections: ["action-columns", "callables", "columns", "company-enrichment", "enrich-column", "enrichment", "projects", "table-action-runs", "table-ingestion-runs", "tables"],
|
|
158
|
-
|
|
158
|
+
// "link"/"join"/"connect"/"relate" route here for `tables link`. Added after a
|
|
159
|
+
// blind user eval asked for exactly "link two tables" and was routed to
|
|
160
|
+
// `tables create` / `columns add` / `enrich-column preview` — none of which
|
|
161
|
+
// do it. The agent only found the right command by grepping the raw 25k-line
|
|
162
|
+
// command manifest, which is not a discovery path a customer has.
|
|
163
|
+
intentTerms: ["table", "rows", "column", "columns", "dataset", "csv", "import", "enrich", "enrichment", "waterfall", "score", "formula", "ai column", "lookup", "link", "link tables", "join", "connect", "relate", "relationship"],
|
|
159
164
|
},
|
|
160
165
|
{
|
|
161
166
|
id: "messages",
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Closed CRM timeline vocabulary exposed to workspace event triggers.
|
|
3
|
+
*
|
|
4
|
+
* The tenant activity writer imports this list as its validation allowlist, and
|
|
5
|
+
* the workflow event catalog imports the same definitions for its presets. That
|
|
6
|
+
* makes it impossible to advertise a CRM activity kind the write path rejects.
|
|
7
|
+
*/
|
|
8
|
+
export declare const CRM_ACTIVITY_CREATED_EVENT = "activity_created";
|
|
9
|
+
export declare const CRM_ACTIVITY_EVENT_DEFINITIONS: readonly [{
|
|
10
|
+
readonly key: "note";
|
|
11
|
+
readonly label: "Note added";
|
|
12
|
+
readonly group: "Notes";
|
|
13
|
+
}, {
|
|
14
|
+
readonly key: "email_sent";
|
|
15
|
+
readonly label: "Email sent";
|
|
16
|
+
readonly group: "Email";
|
|
17
|
+
}, {
|
|
18
|
+
readonly key: "email_received";
|
|
19
|
+
readonly label: "Email received";
|
|
20
|
+
readonly group: "Email";
|
|
21
|
+
}, {
|
|
22
|
+
readonly key: "email_reply";
|
|
23
|
+
readonly label: "Email reply";
|
|
24
|
+
readonly group: "Email";
|
|
25
|
+
}, {
|
|
26
|
+
readonly key: "linkedin_message";
|
|
27
|
+
readonly label: "LinkedIn message";
|
|
28
|
+
readonly group: "LinkedIn";
|
|
29
|
+
}, {
|
|
30
|
+
readonly key: "call";
|
|
31
|
+
readonly label: "Call logged";
|
|
32
|
+
readonly group: "Calls & meetings";
|
|
33
|
+
}, {
|
|
34
|
+
readonly key: "meeting_booked";
|
|
35
|
+
readonly label: "Meeting booked";
|
|
36
|
+
readonly group: "Calls & meetings";
|
|
37
|
+
}, {
|
|
38
|
+
readonly key: "meeting_completed";
|
|
39
|
+
readonly label: "Meeting completed";
|
|
40
|
+
readonly group: "Calls & meetings";
|
|
41
|
+
}, {
|
|
42
|
+
readonly key: "no_show";
|
|
43
|
+
readonly label: "Meeting no-show";
|
|
44
|
+
readonly group: "Outcomes";
|
|
45
|
+
}, {
|
|
46
|
+
readonly key: "stage_changed";
|
|
47
|
+
readonly label: "Stage changed";
|
|
48
|
+
readonly group: "CRM operations";
|
|
49
|
+
}, {
|
|
50
|
+
readonly key: "task_created";
|
|
51
|
+
readonly label: "Task created";
|
|
52
|
+
readonly group: "CRM operations";
|
|
53
|
+
}, {
|
|
54
|
+
readonly key: "task_completed";
|
|
55
|
+
readonly label: "Task completed";
|
|
56
|
+
readonly group: "CRM operations";
|
|
57
|
+
}, {
|
|
58
|
+
readonly key: "record_merged";
|
|
59
|
+
readonly label: "Records merged";
|
|
60
|
+
readonly group: "CRM operations";
|
|
61
|
+
}, {
|
|
62
|
+
readonly key: "enrichment_run";
|
|
63
|
+
readonly label: "Enrichment completed";
|
|
64
|
+
readonly group: "CRM operations";
|
|
65
|
+
}, {
|
|
66
|
+
readonly key: "sync_pushed";
|
|
67
|
+
readonly label: "CRM sync pushed";
|
|
68
|
+
readonly group: "CRM operations";
|
|
69
|
+
}, {
|
|
70
|
+
readonly key: "sync_pulled";
|
|
71
|
+
readonly label: "CRM sync pulled";
|
|
72
|
+
readonly group: "CRM operations";
|
|
73
|
+
}, {
|
|
74
|
+
readonly key: "signup";
|
|
75
|
+
readonly label: "Signup";
|
|
76
|
+
readonly group: "Signals";
|
|
77
|
+
}, {
|
|
78
|
+
readonly key: "website_visit";
|
|
79
|
+
readonly label: "Website visit";
|
|
80
|
+
readonly group: "Signals";
|
|
81
|
+
}, {
|
|
82
|
+
readonly key: "profile_view";
|
|
83
|
+
readonly label: "Profile view";
|
|
84
|
+
readonly group: "Signals";
|
|
85
|
+
}, {
|
|
86
|
+
readonly key: "post_reaction";
|
|
87
|
+
readonly label: "Post reaction";
|
|
88
|
+
readonly group: "Signals";
|
|
89
|
+
}, {
|
|
90
|
+
readonly key: "new_follower";
|
|
91
|
+
readonly label: "New follower";
|
|
92
|
+
readonly group: "Signals";
|
|
93
|
+
}, {
|
|
94
|
+
readonly key: "connection_sent";
|
|
95
|
+
readonly label: "Connection request sent";
|
|
96
|
+
readonly group: "LinkedIn";
|
|
97
|
+
}, {
|
|
98
|
+
readonly key: "connection_accepted";
|
|
99
|
+
readonly label: "Connection accepted";
|
|
100
|
+
readonly group: "LinkedIn";
|
|
101
|
+
}, {
|
|
102
|
+
readonly key: "sequence_enrolled";
|
|
103
|
+
readonly label: "Sequence enrolled";
|
|
104
|
+
readonly group: "Sequences";
|
|
105
|
+
}, {
|
|
106
|
+
readonly key: "sequence_stopped";
|
|
107
|
+
readonly label: "Sequence stopped";
|
|
108
|
+
readonly group: "Sequences";
|
|
109
|
+
}, {
|
|
110
|
+
readonly key: "email_bounced";
|
|
111
|
+
readonly label: "Email bounced";
|
|
112
|
+
readonly group: "Outcomes";
|
|
113
|
+
}, {
|
|
114
|
+
readonly key: "unsubscribed";
|
|
115
|
+
readonly label: "Unsubscribed";
|
|
116
|
+
readonly group: "Outcomes";
|
|
117
|
+
}, {
|
|
118
|
+
readonly key: "spam_complaint";
|
|
119
|
+
readonly label: "Spam complaint";
|
|
120
|
+
readonly group: "Outcomes";
|
|
121
|
+
}, {
|
|
122
|
+
readonly key: "whatsapp_message";
|
|
123
|
+
readonly label: "WhatsApp message";
|
|
124
|
+
readonly group: "WhatsApp";
|
|
125
|
+
}];
|
|
126
|
+
export type CrmActivityType = (typeof CRM_ACTIVITY_EVENT_DEFINITIONS)[number]["key"];
|
|
127
|
+
export declare const CRM_ACTIVITY_TYPES: readonly CrmActivityType[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Closed CRM timeline vocabulary exposed to workspace event triggers.
|
|
3
|
+
*
|
|
4
|
+
* The tenant activity writer imports this list as its validation allowlist, and
|
|
5
|
+
* the workflow event catalog imports the same definitions for its presets. That
|
|
6
|
+
* makes it impossible to advertise a CRM activity kind the write path rejects.
|
|
7
|
+
*/
|
|
8
|
+
export const CRM_ACTIVITY_CREATED_EVENT = "activity_created";
|
|
9
|
+
export const CRM_ACTIVITY_EVENT_DEFINITIONS = [
|
|
10
|
+
{ key: "note", label: "Note added", group: "Notes" },
|
|
11
|
+
{ key: "email_sent", label: "Email sent", group: "Email" },
|
|
12
|
+
{ key: "email_received", label: "Email received", group: "Email" },
|
|
13
|
+
{ key: "email_reply", label: "Email reply", group: "Email" },
|
|
14
|
+
{ key: "linkedin_message", label: "LinkedIn message", group: "LinkedIn" },
|
|
15
|
+
{ key: "call", label: "Call logged", group: "Calls & meetings" },
|
|
16
|
+
{ key: "meeting_booked", label: "Meeting booked", group: "Calls & meetings" },
|
|
17
|
+
{ key: "meeting_completed", label: "Meeting completed", group: "Calls & meetings" },
|
|
18
|
+
{ key: "no_show", label: "Meeting no-show", group: "Outcomes" },
|
|
19
|
+
{ key: "stage_changed", label: "Stage changed", group: "CRM operations" },
|
|
20
|
+
{ key: "task_created", label: "Task created", group: "CRM operations" },
|
|
21
|
+
{ key: "task_completed", label: "Task completed", group: "CRM operations" },
|
|
22
|
+
{ key: "record_merged", label: "Records merged", group: "CRM operations" },
|
|
23
|
+
{ key: "enrichment_run", label: "Enrichment completed", group: "CRM operations" },
|
|
24
|
+
{ key: "sync_pushed", label: "CRM sync pushed", group: "CRM operations" },
|
|
25
|
+
{ key: "sync_pulled", label: "CRM sync pulled", group: "CRM operations" },
|
|
26
|
+
{ key: "signup", label: "Signup", group: "Signals" },
|
|
27
|
+
{ key: "website_visit", label: "Website visit", group: "Signals" },
|
|
28
|
+
{ key: "profile_view", label: "Profile view", group: "Signals" },
|
|
29
|
+
{ key: "post_reaction", label: "Post reaction", group: "Signals" },
|
|
30
|
+
{ key: "new_follower", label: "New follower", group: "Signals" },
|
|
31
|
+
{ key: "connection_sent", label: "Connection request sent", group: "LinkedIn" },
|
|
32
|
+
{ key: "connection_accepted", label: "Connection accepted", group: "LinkedIn" },
|
|
33
|
+
{ key: "sequence_enrolled", label: "Sequence enrolled", group: "Sequences" },
|
|
34
|
+
{ key: "sequence_stopped", label: "Sequence stopped", group: "Sequences" },
|
|
35
|
+
{ key: "email_bounced", label: "Email bounced", group: "Outcomes" },
|
|
36
|
+
{ key: "unsubscribed", label: "Unsubscribed", group: "Outcomes" },
|
|
37
|
+
{ key: "spam_complaint", label: "Spam complaint", group: "Outcomes" },
|
|
38
|
+
{ key: "whatsapp_message", label: "WhatsApp message", group: "WhatsApp" },
|
|
39
|
+
];
|
|
40
|
+
export const CRM_ACTIVITY_TYPES = CRM_ACTIVITY_EVENT_DEFINITIONS.map((definition) => definition.key);
|
|
@@ -18,6 +18,49 @@ export declare const CRM_WORKFLOW_EVENT_SOURCE = "crm";
|
|
|
18
18
|
* consumes is a dead signal.
|
|
19
19
|
*/
|
|
20
20
|
export declare const CRM_EMAIL_REPLY_CLASSIFIED_EVENT = "email_reply_classified";
|
|
21
|
+
/** App-native CRM events that can start ordinary workspace workflows. */
|
|
22
|
+
export declare const CRM_SIGNUP_EVENT = "signup";
|
|
23
|
+
export declare const CRM_WEBSITE_VISIT_EVENT = "website_visit";
|
|
24
|
+
export declare const CRM_PROFILE_VIEW_EVENT = "profile_view";
|
|
25
|
+
export declare const CRM_POST_ENGAGER_EVENT = "post_engager";
|
|
26
|
+
export declare const CRM_NEW_FOLLOWER_EVENT = "new_follower";
|
|
27
|
+
export declare const CRM_SIGNAL_WORKFLOW_EVENT_DEFINITIONS: readonly [{
|
|
28
|
+
readonly event: "email_reply_classified";
|
|
29
|
+
readonly label: "Reply classified";
|
|
30
|
+
readonly group: "Replies";
|
|
31
|
+
readonly description: "An inbound email, LinkedIn, or WhatsApp reply received a CRM classification.";
|
|
32
|
+
readonly payloadFields: readonly ["channel", "status", "email", "linkedin_url", "external_id", "conversation_id", "conversation_url", "counterpart_name", "message", "sequence_id", "enrollment_id", "primary_source"];
|
|
33
|
+
}, {
|
|
34
|
+
readonly event: "signup";
|
|
35
|
+
readonly label: "Signup received";
|
|
36
|
+
readonly group: "Lifecycle";
|
|
37
|
+
readonly description: "A product or workspace signup was recorded for CRM routing.";
|
|
38
|
+
readonly payloadFields: readonly ["event_id", "occurred_at", "email", "first_name", "last_name", "company_domain", "company_name", "linkedin_url", "attribution", "channel", "provider"];
|
|
39
|
+
}, {
|
|
40
|
+
readonly event: "website_visit";
|
|
41
|
+
readonly label: "Website visit received";
|
|
42
|
+
readonly group: "Signals";
|
|
43
|
+
readonly description: "A known visitor signal was recorded against the CRM.";
|
|
44
|
+
readonly payloadFields: readonly ["email", "linkedin_url", "first_name", "last_name", "company_domain", "company_name", "provider_event_id", "session_id", "page_url"];
|
|
45
|
+
}, {
|
|
46
|
+
readonly event: "profile_view";
|
|
47
|
+
readonly label: "Profile view received";
|
|
48
|
+
readonly group: "Signals";
|
|
49
|
+
readonly description: "A profile-view signal was recorded against the CRM.";
|
|
50
|
+
readonly payloadFields: readonly ["email", "linkedin_url", "first_name", "last_name", "company_domain", "company_name", "provider_event_id"];
|
|
51
|
+
}, {
|
|
52
|
+
readonly event: "post_engager";
|
|
53
|
+
readonly label: "Post engagement received";
|
|
54
|
+
readonly group: "Signals";
|
|
55
|
+
readonly description: "A post-reaction or comment signal was recorded against the CRM.";
|
|
56
|
+
readonly payloadFields: readonly ["email", "linkedin_url", "first_name", "last_name", "company_domain", "company_name", "provider_event_id", "post_url"];
|
|
57
|
+
}, {
|
|
58
|
+
readonly event: "new_follower";
|
|
59
|
+
readonly label: "New follower received";
|
|
60
|
+
readonly group: "Signals";
|
|
61
|
+
readonly description: "A new-follower signal was recorded against the CRM.";
|
|
62
|
+
readonly payloadFields: readonly ["email", "linkedin_url", "first_name", "last_name", "company_domain", "company_name", "provider_event_id"];
|
|
63
|
+
}];
|
|
21
64
|
/**
|
|
22
65
|
* Channel an inbound CRM signal arrived on. Selects which person identity the
|
|
23
66
|
* standing lead-stage router resolves on (email → email, linkedin →
|
|
@@ -18,6 +18,116 @@ export const CRM_WORKFLOW_EVENT_SOURCE = "crm";
|
|
|
18
18
|
* consumes is a dead signal.
|
|
19
19
|
*/
|
|
20
20
|
export const CRM_EMAIL_REPLY_CLASSIFIED_EVENT = "email_reply_classified";
|
|
21
|
+
/** App-native CRM events that can start ordinary workspace workflows. */
|
|
22
|
+
export const CRM_SIGNUP_EVENT = "signup";
|
|
23
|
+
export const CRM_WEBSITE_VISIT_EVENT = "website_visit";
|
|
24
|
+
export const CRM_PROFILE_VIEW_EVENT = "profile_view";
|
|
25
|
+
export const CRM_POST_ENGAGER_EVENT = "post_engager";
|
|
26
|
+
export const CRM_NEW_FOLLOWER_EVENT = "new_follower";
|
|
27
|
+
export const CRM_SIGNAL_WORKFLOW_EVENT_DEFINITIONS = [
|
|
28
|
+
{
|
|
29
|
+
event: CRM_EMAIL_REPLY_CLASSIFIED_EVENT,
|
|
30
|
+
label: "Reply classified",
|
|
31
|
+
group: "Replies",
|
|
32
|
+
description: "An inbound email, LinkedIn, or WhatsApp reply received a CRM classification.",
|
|
33
|
+
payloadFields: [
|
|
34
|
+
"channel",
|
|
35
|
+
"status",
|
|
36
|
+
"email",
|
|
37
|
+
"linkedin_url",
|
|
38
|
+
"external_id",
|
|
39
|
+
"conversation_id",
|
|
40
|
+
"conversation_url",
|
|
41
|
+
"counterpart_name",
|
|
42
|
+
"message",
|
|
43
|
+
"sequence_id",
|
|
44
|
+
"enrollment_id",
|
|
45
|
+
"primary_source",
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
event: CRM_SIGNUP_EVENT,
|
|
50
|
+
label: "Signup received",
|
|
51
|
+
group: "Lifecycle",
|
|
52
|
+
description: "A product or workspace signup was recorded for CRM routing.",
|
|
53
|
+
payloadFields: [
|
|
54
|
+
"event_id",
|
|
55
|
+
"occurred_at",
|
|
56
|
+
"email",
|
|
57
|
+
"first_name",
|
|
58
|
+
"last_name",
|
|
59
|
+
"company_domain",
|
|
60
|
+
"company_name",
|
|
61
|
+
"linkedin_url",
|
|
62
|
+
"attribution",
|
|
63
|
+
"channel",
|
|
64
|
+
"provider",
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
event: CRM_WEBSITE_VISIT_EVENT,
|
|
69
|
+
label: "Website visit received",
|
|
70
|
+
group: "Signals",
|
|
71
|
+
description: "A known visitor signal was recorded against the CRM.",
|
|
72
|
+
payloadFields: [
|
|
73
|
+
"email",
|
|
74
|
+
"linkedin_url",
|
|
75
|
+
"first_name",
|
|
76
|
+
"last_name",
|
|
77
|
+
"company_domain",
|
|
78
|
+
"company_name",
|
|
79
|
+
"provider_event_id",
|
|
80
|
+
"session_id",
|
|
81
|
+
"page_url",
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
event: CRM_PROFILE_VIEW_EVENT,
|
|
86
|
+
label: "Profile view received",
|
|
87
|
+
group: "Signals",
|
|
88
|
+
description: "A profile-view signal was recorded against the CRM.",
|
|
89
|
+
payloadFields: [
|
|
90
|
+
"email",
|
|
91
|
+
"linkedin_url",
|
|
92
|
+
"first_name",
|
|
93
|
+
"last_name",
|
|
94
|
+
"company_domain",
|
|
95
|
+
"company_name",
|
|
96
|
+
"provider_event_id",
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
event: CRM_POST_ENGAGER_EVENT,
|
|
101
|
+
label: "Post engagement received",
|
|
102
|
+
group: "Signals",
|
|
103
|
+
description: "A post-reaction or comment signal was recorded against the CRM.",
|
|
104
|
+
payloadFields: [
|
|
105
|
+
"email",
|
|
106
|
+
"linkedin_url",
|
|
107
|
+
"first_name",
|
|
108
|
+
"last_name",
|
|
109
|
+
"company_domain",
|
|
110
|
+
"company_name",
|
|
111
|
+
"provider_event_id",
|
|
112
|
+
"post_url",
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
event: CRM_NEW_FOLLOWER_EVENT,
|
|
117
|
+
label: "New follower received",
|
|
118
|
+
group: "Signals",
|
|
119
|
+
description: "A new-follower signal was recorded against the CRM.",
|
|
120
|
+
payloadFields: [
|
|
121
|
+
"email",
|
|
122
|
+
"linkedin_url",
|
|
123
|
+
"first_name",
|
|
124
|
+
"last_name",
|
|
125
|
+
"company_domain",
|
|
126
|
+
"company_name",
|
|
127
|
+
"provider_event_id",
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
];
|
|
21
131
|
/**
|
|
22
132
|
* Deterministic external event id for one conversation settling on one status.
|
|
23
133
|
*
|
|
@@ -12,6 +12,7 @@ export * from "./cli-envelope.js";
|
|
|
12
12
|
export * from "./cli-login-code.js";
|
|
13
13
|
export * from "./cli-result.js";
|
|
14
14
|
export * from "./crm-reply-events.js";
|
|
15
|
+
export * from "./crm-activity-events.js";
|
|
15
16
|
export * from "./column-types.js";
|
|
16
17
|
export * from "./copilot-journeys.js";
|
|
17
18
|
export * from "./credit-guidance.js";
|
|
@@ -54,6 +55,7 @@ export * from "./timing.js";
|
|
|
54
55
|
export * from "./type-guards.js";
|
|
55
56
|
export * from "./worker-failures-queue.js";
|
|
56
57
|
export * from "./workflow-mcp-tools.js";
|
|
58
|
+
export * from "./workspace-event-catalog.js";
|
|
57
59
|
export * from "./workspace-agents.js";
|
|
58
60
|
export declare const MAX_ROW_LOOP_WRITE_ROWS = 500;
|
|
59
61
|
export type SemanticVersion = {
|
|
@@ -12,6 +12,7 @@ export * from "./cli-envelope.js";
|
|
|
12
12
|
export * from "./cli-login-code.js";
|
|
13
13
|
export * from "./cli-result.js";
|
|
14
14
|
export * from "./crm-reply-events.js";
|
|
15
|
+
export * from "./crm-activity-events.js";
|
|
15
16
|
export * from "./column-types.js";
|
|
16
17
|
export * from "./copilot-journeys.js";
|
|
17
18
|
export * from "./credit-guidance.js";
|
|
@@ -58,6 +59,7 @@ export * from "./timing.js";
|
|
|
58
59
|
export * from "./type-guards.js";
|
|
59
60
|
export * from "./worker-failures-queue.js";
|
|
60
61
|
export * from "./workflow-mcp-tools.js";
|
|
62
|
+
export * from "./workspace-event-catalog.js";
|
|
61
63
|
export * from "./workspace-agents.js";
|
|
62
64
|
// Maximum rows a single row-loop write (insert/upsert/preview) may process. The
|
|
63
65
|
// row-loop engine issues one DB round-trip per row, so a 500-row write already
|
|
@@ -287,5 +287,5 @@ export declare const SEQUENCE_HUBSPOT_EVENT_SYNC_TEMPLATE_ID = "sequencer-hubspo
|
|
|
287
287
|
export declare const SEQUENCE_WORKFLOW_EVENT_SOURCE = "sequencer";
|
|
288
288
|
export declare const SEQUENCE_CONTACT_ACTIVITY_EVENT = "contact_activity";
|
|
289
289
|
export declare const SEQUENCE_HUBSPOT_LINKEDIN_IDENTITY_PROPERTY = "oxygen_linkedin_url";
|
|
290
|
-
export declare const DEFAULT_SEQUENCE_HUBSPOT_EVENT_MAPPINGS: Readonly<Record<"linkedin_profile_visited" | "linkedin_connection_sent" | "linkedin_connection_accepted" | "linkedin_message_sent" | "linkedin_inmail_sent" | "linkedin_reply_received" | "linkedin_followed" | "linkedin_post_liked" | "linkedin_post_commented" | "linkedin_connection_withdrawn" | "
|
|
290
|
+
export declare const DEFAULT_SEQUENCE_HUBSPOT_EVENT_MAPPINGS: Readonly<Record<"email_sent" | "meeting_booked" | "email_bounced" | "linkedin_profile_visited" | "linkedin_connection_sent" | "linkedin_connection_accepted" | "linkedin_message_sent" | "linkedin_inmail_sent" | "linkedin_reply_received" | "linkedin_followed" | "linkedin_post_liked" | "linkedin_post_commented" | "linkedin_connection_withdrawn" | "email_campaign_enrolled" | "email_campaign_moved" | "email_campaign_stopped" | "email_opened" | "email_clicked" | "email_reply_received" | "email_unsubscribed" | "email_spam_complaint" | "whatsapp_message_sent" | "whatsapp_reply_received" | "call_task_created" | "call_connected" | "call_no_answer" | "call_voicemail" | "crm_task_created", string>>;
|
|
291
291
|
export declare function isSequenceCrmEventKey(value: unknown): value is SequenceCrmEventKey;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const OXYGEN_VERSION = "1.
|
|
1
|
+
export const OXYGEN_VERSION = "1.618.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:
|
|
@@ -30,14 +30,14 @@ export type WorkspaceAgentDescriptor = {
|
|
|
30
30
|
deepLinkKind: WorkspaceAgentDeepLinkKind;
|
|
31
31
|
};
|
|
32
32
|
/**
|
|
33
|
-
* A single run
|
|
33
|
+
* A single run a built-in or user-defined Agent produced. Field names align with the
|
|
34
34
|
* observability run vocabulary so the cross-primitive runs console can consume
|
|
35
35
|
* these without a parallel shape. Nulls are explicit (never omitted) so every
|
|
36
36
|
* consumer reads the same keys regardless of specialist.
|
|
37
37
|
*/
|
|
38
38
|
export type WorkspaceAgentRunItem = {
|
|
39
|
-
/** The
|
|
40
|
-
slug:
|
|
39
|
+
/** The built-in or user-defined Agent that produced this run. */
|
|
40
|
+
slug: string;
|
|
41
41
|
/** The run's stable id (draft id / session id / knowledge-log id). */
|
|
42
42
|
id: string;
|
|
43
43
|
/** The kind of artifact this run produced. */
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
// behavior elsewhere in the product, surfaced under /agents and `oxygen agent`.
|
|
7
7
|
// Agents are governed workspace workers: the runtime envelope (approval posture,
|
|
8
8
|
// credit budgets, run observability) is platform-enforced, never agent-optional.
|
|
9
|
-
// User-defined custom
|
|
10
|
-
//
|
|
11
|
-
// and
|
|
12
|
-
//
|
|
13
|
-
//
|
|
9
|
+
// User-defined custom Agents use the same runtime but stay outside this built-in
|
|
10
|
+
// descriptor roster: their tenant-owned definitions come from the custom Agent
|
|
11
|
+
// API and their runs join the shared history dynamically. There are never
|
|
12
|
+
// placeholder rows. CRM-hygiene, deliverability, and any other roadmap Agent stay
|
|
13
|
+
// OUT until they ship — the no-placeholder-surface rule.
|
|
14
14
|
//
|
|
15
15
|
// This module is a dependency-free leaf (pure descriptors + types) so it can live
|
|
16
16
|
// in @oxygen/shared without importing tenant-db: the actual per-agent wiring
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type WorkspaceEventCatalogFilter = {
|
|
2
|
+
path: string;
|
|
3
|
+
op: "eq";
|
|
4
|
+
value: string;
|
|
5
|
+
};
|
|
6
|
+
export type WorkspaceEventCatalogEntry = {
|
|
7
|
+
/** Stable catalog identity; independent of the underlying source/event pair. */
|
|
8
|
+
id: string;
|
|
9
|
+
source: string;
|
|
10
|
+
event: string;
|
|
11
|
+
group: string;
|
|
12
|
+
label: string;
|
|
13
|
+
description: string;
|
|
14
|
+
filters?: readonly WorkspaceEventCatalogFilter[];
|
|
15
|
+
payloadFields: readonly string[];
|
|
16
|
+
};
|
|
17
|
+
export declare const WORKSPACE_EVENT_CATALOG_VERSION = 1;
|
|
18
|
+
/**
|
|
19
|
+
* Every app-native workspace event that has a durable or explicitly callable
|
|
20
|
+
* producer. Integration-specific subscriptions are merged in at request time.
|
|
21
|
+
*/
|
|
22
|
+
export declare const WORKSPACE_EVENT_CATALOG: readonly WorkspaceEventCatalogEntry[];
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { CRM_ACTIVITY_CREATED_EVENT, CRM_ACTIVITY_EVENT_DEFINITIONS, } from "./crm-activity-events.js";
|
|
2
|
+
import { CRM_SIGNAL_WORKFLOW_EVENT_DEFINITIONS, CRM_WORKFLOW_EVENT_SOURCE, } from "./crm-reply-events.js";
|
|
3
|
+
import { SEQUENCE_CONTACT_ACTIVITY_EVENT, SEQUENCE_CRM_EVENT_DEFINITIONS, SEQUENCE_WORKFLOW_EVENT_SOURCE, } from "./sequence-crm-events.js";
|
|
4
|
+
import { SEQUENCE_ENROLLMENT_TERMINAL_EVENT, SEQUENCE_TERMINAL_EVENT_SOURCE, SEQUENCE_TERMINAL_STATUSES, } from "./sequence-terminal-events.js";
|
|
5
|
+
export const WORKSPACE_EVENT_CATALOG_VERSION = 1;
|
|
6
|
+
const sequenceActivityFields = [
|
|
7
|
+
"event",
|
|
8
|
+
"occurred_at",
|
|
9
|
+
"sequence_id",
|
|
10
|
+
"enrollment_id",
|
|
11
|
+
"email",
|
|
12
|
+
"linkedin_url",
|
|
13
|
+
"lead_name",
|
|
14
|
+
];
|
|
15
|
+
const sequenceTerminalFields = [
|
|
16
|
+
"occurred_at",
|
|
17
|
+
"sequence_id",
|
|
18
|
+
"enrollment_id",
|
|
19
|
+
"status",
|
|
20
|
+
"reason",
|
|
21
|
+
"endpoint_id",
|
|
22
|
+
"endpoint_kind",
|
|
23
|
+
"step_id",
|
|
24
|
+
"branch_id",
|
|
25
|
+
"branch_arm",
|
|
26
|
+
"lead_name",
|
|
27
|
+
"email",
|
|
28
|
+
"linkedin_url",
|
|
29
|
+
];
|
|
30
|
+
const crmActivityFields = [
|
|
31
|
+
"activity_id",
|
|
32
|
+
"activity_type",
|
|
33
|
+
"occurred_at",
|
|
34
|
+
"channel",
|
|
35
|
+
"direction",
|
|
36
|
+
"summary",
|
|
37
|
+
"body",
|
|
38
|
+
"source_type",
|
|
39
|
+
"source_provider",
|
|
40
|
+
"provider_event_id",
|
|
41
|
+
"run_id",
|
|
42
|
+
"metadata",
|
|
43
|
+
"links",
|
|
44
|
+
];
|
|
45
|
+
function sequenceActivityDescription(key, label) {
|
|
46
|
+
if (key === "email_bounced") {
|
|
47
|
+
return "An outreach sequence enrollment reported an email bounce. Use the CRM timeline preset instead for any bounce activity logged on a CRM record.";
|
|
48
|
+
}
|
|
49
|
+
if (key === "meeting_booked") {
|
|
50
|
+
return "An outreach sequence enrollment reported a booked meeting. Use the CRM timeline preset instead for any meeting-booked activity logged on a CRM record.";
|
|
51
|
+
}
|
|
52
|
+
return `A sequence emitted the ${label.toLowerCase()} outcome.`;
|
|
53
|
+
}
|
|
54
|
+
function crmActivityDescription(key, label) {
|
|
55
|
+
if (key === "email_bounced") {
|
|
56
|
+
return "An email-bounce activity was added to a CRM record timeline, regardless of which producer logged it. Use the Sequencer preset for an outreach enrollment's own bounce outcome.";
|
|
57
|
+
}
|
|
58
|
+
if (key === "meeting_booked") {
|
|
59
|
+
return "A meeting-booked activity was added to a CRM record timeline, regardless of which producer logged it. Use the Sequencer preset for an outreach enrollment's own meeting outcome.";
|
|
60
|
+
}
|
|
61
|
+
return `A ${label.toLowerCase()} activity was added to a CRM timeline.`;
|
|
62
|
+
}
|
|
63
|
+
const sequenceActivityEntries = [
|
|
64
|
+
{
|
|
65
|
+
id: "sequencer.contact_activity.any",
|
|
66
|
+
source: SEQUENCE_WORKFLOW_EVENT_SOURCE,
|
|
67
|
+
event: SEQUENCE_CONTACT_ACTIVITY_EVENT,
|
|
68
|
+
group: "Sequencer · All activity",
|
|
69
|
+
label: "Any contact activity",
|
|
70
|
+
description: "Any durable contact activity emitted by any sequence in this workspace.",
|
|
71
|
+
payloadFields: sequenceActivityFields,
|
|
72
|
+
},
|
|
73
|
+
...SEQUENCE_CRM_EVENT_DEFINITIONS.map((definition) => ({
|
|
74
|
+
id: `sequencer.contact_activity.${definition.key}`,
|
|
75
|
+
source: SEQUENCE_WORKFLOW_EVENT_SOURCE,
|
|
76
|
+
event: SEQUENCE_CONTACT_ACTIVITY_EVENT,
|
|
77
|
+
group: `Sequencer · ${definition.group}`,
|
|
78
|
+
label: definition.label,
|
|
79
|
+
description: sequenceActivityDescription(definition.key, definition.label),
|
|
80
|
+
filters: [{ path: "event", op: "eq", value: definition.key }],
|
|
81
|
+
payloadFields: sequenceActivityFields,
|
|
82
|
+
})),
|
|
83
|
+
];
|
|
84
|
+
const sequenceTerminalEntries = [
|
|
85
|
+
{
|
|
86
|
+
id: "sequencer.enrollment_terminal.any",
|
|
87
|
+
source: SEQUENCE_TERMINAL_EVENT_SOURCE,
|
|
88
|
+
event: SEQUENCE_ENROLLMENT_TERMINAL_EVENT,
|
|
89
|
+
group: "Sequencer · Journey status",
|
|
90
|
+
label: "Any terminal enrollment",
|
|
91
|
+
description: "Any sequence enrollment reached a terminal state or visible graph endpoint.",
|
|
92
|
+
payloadFields: sequenceTerminalFields,
|
|
93
|
+
},
|
|
94
|
+
...SEQUENCE_TERMINAL_STATUSES.map((status) => ({
|
|
95
|
+
id: `sequencer.enrollment_terminal.${status}`,
|
|
96
|
+
source: SEQUENCE_TERMINAL_EVENT_SOURCE,
|
|
97
|
+
event: SEQUENCE_ENROLLMENT_TERMINAL_EVENT,
|
|
98
|
+
group: "Sequencer · Journey status",
|
|
99
|
+
label: `Enrollment ${status}`,
|
|
100
|
+
description: `A sequence enrollment became ${status}.`,
|
|
101
|
+
filters: [{ path: "status", op: "eq", value: status }],
|
|
102
|
+
payloadFields: sequenceTerminalFields,
|
|
103
|
+
})),
|
|
104
|
+
];
|
|
105
|
+
const crmActivityEntries = [
|
|
106
|
+
{
|
|
107
|
+
id: "crm.activity_created.any",
|
|
108
|
+
source: CRM_WORKFLOW_EVENT_SOURCE,
|
|
109
|
+
event: CRM_ACTIVITY_CREATED_EVENT,
|
|
110
|
+
group: "CRM · All timeline activity",
|
|
111
|
+
label: "Any CRM activity",
|
|
112
|
+
description: "Any non-workflow-authored activity was added to a CRM record timeline.",
|
|
113
|
+
payloadFields: crmActivityFields,
|
|
114
|
+
},
|
|
115
|
+
...CRM_ACTIVITY_EVENT_DEFINITIONS.map((definition) => ({
|
|
116
|
+
id: `crm.activity_created.${definition.key}`,
|
|
117
|
+
source: CRM_WORKFLOW_EVENT_SOURCE,
|
|
118
|
+
event: CRM_ACTIVITY_CREATED_EVENT,
|
|
119
|
+
group: `CRM · ${definition.group}`,
|
|
120
|
+
label: definition.label,
|
|
121
|
+
description: crmActivityDescription(definition.key, definition.label),
|
|
122
|
+
filters: [{ path: "activity_type", op: "eq", value: definition.key }],
|
|
123
|
+
payloadFields: crmActivityFields,
|
|
124
|
+
})),
|
|
125
|
+
];
|
|
126
|
+
const crmSignalEntries = CRM_SIGNAL_WORKFLOW_EVENT_DEFINITIONS.map((definition) => ({
|
|
127
|
+
id: `crm.${definition.event}`,
|
|
128
|
+
source: CRM_WORKFLOW_EVENT_SOURCE,
|
|
129
|
+
event: definition.event,
|
|
130
|
+
group: `CRM · ${definition.group}`,
|
|
131
|
+
label: definition.label,
|
|
132
|
+
description: definition.description,
|
|
133
|
+
payloadFields: definition.payloadFields,
|
|
134
|
+
}));
|
|
135
|
+
/**
|
|
136
|
+
* Every app-native workspace event that has a durable or explicitly callable
|
|
137
|
+
* producer. Integration-specific subscriptions are merged in at request time.
|
|
138
|
+
*/
|
|
139
|
+
export const WORKSPACE_EVENT_CATALOG = [
|
|
140
|
+
...sequenceActivityEntries,
|
|
141
|
+
...sequenceTerminalEntries,
|
|
142
|
+
...crmActivityEntries,
|
|
143
|
+
...crmSignalEntries,
|
|
144
|
+
];
|