@oxygen-agent/cli 1.936.1 → 1.982.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +1 -1
  2. package/dist/admin-primary-providers-render.js +9 -1
  3. package/dist/cli-values.d.ts +14 -0
  4. package/dist/cli-values.js +26 -0
  5. package/dist/command-manifest.js +30 -2
  6. package/dist/functions-commands.js +13 -5
  7. package/dist/help.js +2 -0
  8. package/dist/index.js +1509 -290
  9. package/dist/knowledge-repository-commands.d.ts +6 -0
  10. package/dist/knowledge-repository-commands.js +198 -0
  11. package/dist/skills.js +20 -0
  12. package/dist/ugc-commands.js +470 -15
  13. package/node_modules/@oxygen/recipe-sdk/dist/index.d.ts +2 -0
  14. package/node_modules/@oxygen/shared/dist/byok-connect.d.ts +11 -6
  15. package/node_modules/@oxygen/shared/dist/byok-connect.js +14 -6
  16. package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +8 -0
  17. package/node_modules/@oxygen/shared/dist/capability-discovery.js +152 -20
  18. package/node_modules/@oxygen/shared/dist/copilot-errors.js +3 -0
  19. package/node_modules/@oxygen/shared/dist/copilot-journeys.d.ts +19 -1
  20. package/node_modules/@oxygen/shared/dist/copilot-journeys.generated.d.ts +19 -0
  21. package/node_modules/@oxygen/shared/dist/copilot-journeys.generated.js +26 -0
  22. package/node_modules/@oxygen/shared/dist/copilot-journeys.js +8 -41
  23. package/node_modules/@oxygen/shared/dist/email-dsn.d.ts +60 -0
  24. package/node_modules/@oxygen/shared/dist/email-dsn.js +120 -0
  25. package/node_modules/@oxygen/shared/dist/email-warmup-readiness.d.ts +64 -0
  26. package/node_modules/@oxygen/shared/dist/email-warmup-readiness.js +90 -0
  27. package/node_modules/@oxygen/shared/dist/inbox-avatar-url.d.ts +28 -0
  28. package/node_modules/@oxygen/shared/dist/inbox-avatar-url.js +57 -0
  29. package/node_modules/@oxygen/shared/dist/index.d.ts +10 -0
  30. package/node_modules/@oxygen/shared/dist/index.js +10 -0
  31. package/node_modules/@oxygen/shared/dist/knowledge-bases.d.ts +74 -0
  32. package/node_modules/@oxygen/shared/dist/knowledge-bases.js +456 -0
  33. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.d.ts +56 -48
  34. package/node_modules/@oxygen/shared/dist/knowledge-bootstrap.js +50 -49
  35. package/node_modules/@oxygen/shared/dist/knowledge-repository.d.ts +22 -0
  36. package/node_modules/@oxygen/shared/dist/knowledge-repository.js +121 -0
  37. package/node_modules/@oxygen/shared/dist/knowledge-vault-markdown.d.ts +20 -0
  38. package/node_modules/@oxygen/shared/dist/knowledge-vault-markdown.js +155 -0
  39. package/node_modules/@oxygen/shared/dist/langfuse.d.ts +8 -3
  40. package/node_modules/@oxygen/shared/dist/langfuse.js +177 -130
  41. package/node_modules/@oxygen/shared/dist/llm-payload.d.ts +10 -0
  42. package/node_modules/@oxygen/shared/dist/llm-payload.js +54 -0
  43. package/node_modules/@oxygen/shared/dist/llm-usage.d.ts +11 -0
  44. package/node_modules/@oxygen/shared/dist/llm-usage.js +30 -0
  45. package/node_modules/@oxygen/shared/dist/mailbox-import.d.ts +10 -0
  46. package/node_modules/@oxygen/shared/dist/mailbox-import.js +53 -0
  47. package/node_modules/@oxygen/shared/dist/plan-limits.d.ts +8 -0
  48. package/node_modules/@oxygen/shared/dist/plan-limits.js +8 -0
  49. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +1 -1
  50. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +1 -1
  51. package/node_modules/@oxygen/shared/dist/product-analytics-core.d.ts +98 -0
  52. package/node_modules/@oxygen/shared/dist/product-analytics-core.js +159 -0
  53. package/node_modules/@oxygen/shared/dist/product-analytics-environment.d.ts +18 -0
  54. package/node_modules/@oxygen/shared/dist/product-analytics-environment.js +46 -0
  55. package/node_modules/@oxygen/shared/dist/product-analytics-events.d.ts +116 -0
  56. package/node_modules/@oxygen/shared/dist/product-analytics-events.js +120 -0
  57. package/node_modules/@oxygen/shared/dist/recipes.d.ts +6 -0
  58. package/node_modules/@oxygen/shared/dist/recipes.js +23 -0
  59. package/node_modules/@oxygen/shared/dist/sequences.d.ts +126 -2
  60. package/node_modules/@oxygen/shared/dist/sequences.js +280 -4
  61. package/node_modules/@oxygen/shared/dist/ugc-amplification-identity.d.ts +2 -0
  62. package/node_modules/@oxygen/shared/dist/ugc-amplification-identity.js +24 -0
  63. package/node_modules/@oxygen/shared/dist/ugc.d.ts +29 -1
  64. package/node_modules/@oxygen/shared/dist/user-capability-routing.js +8 -1
  65. package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
  66. package/node_modules/@oxygen/shared/dist/version.js +3 -1
  67. package/node_modules/@oxygen/shared/dist/workspace-file-storage.d.ts +6 -2
  68. package/node_modules/@oxygen/shared/dist/workspace-file-storage.js +15 -4
  69. package/node_modules/@oxygen/shared/package.json +15 -0
  70. package/node_modules/@oxygen/workflows/dist/graph/lint.js +22 -0
  71. package/package.json +2 -1
package/README.md CHANGED
@@ -34,4 +34,4 @@ oxygen update
34
34
 
35
35
  For product documentation, visit https://oxygen-agent.com/docs. For support, visit https://oxygen-agent.com.
36
36
 
37
- Version: 1.936.1
37
+ Version: 1.982.3
@@ -274,6 +274,13 @@ function renderProvider(row, now, binary) {
274
274
  const provider = str(row.provider) ?? "?";
275
275
  const level = str(posture.level) ?? "unknown";
276
276
  const functions = arr(row.functions).map((fn) => String(fn));
277
+ // A catch-all escalation lane is the only route to its provider and is
278
+ // declared outside the chain's steps; name it so the row does not read as a
279
+ // plain primary for an intent it never leads.
280
+ const escalations = arr(row.primary_for)
281
+ .map((role) => obj(role))
282
+ .filter((role) => role !== null && str(role.role) === "catch_all_escalation")
283
+ .map((role) => str(role.intent) ?? "?");
277
284
  const probe = str(health.probe) ?? "none";
278
285
  const healthStatus = str(health.latest_status) ?? (probe === "none" ? "unmonitored" : "no data");
279
286
  const healthDetail = [
@@ -284,7 +291,8 @@ function renderProvider(row, now, binary) {
284
291
  (num(health.auth_error_pct_96h) ?? 0) > 0 ? `${pct(health.auth_error_pct_96h)} auth-error` : null,
285
292
  num(health.last_latency_ms) === null ? null : `${count(health.last_latency_ms)} ms`,
286
293
  ].filter((part) => part !== null);
287
- lines.push(` - ${provider} [${level}]${functions.length > 0 ? ` ${functions.join("+")}` : ""} · ` +
294
+ lines.push(` - ${provider} [${level}]${functions.length > 0 ? ` ${functions.join("+")}` : ""}` +
295
+ `${escalations.length > 0 ? ` (catch-all escalation: ${escalations.join(", ")})` : ""} · ` +
288
296
  `key ${row.key_configured === false ? `NOT SET (${str(row.managed_key_env_var) ?? "—"})` : str(row.managed_key_env_var) ?? "customer-supplied"} · ` +
289
297
  `health ${healthStatus} (${healthDetail.join(", ")})`);
290
298
  const scope = str(traffic.scope) ?? "workspace_attributed";
@@ -1,5 +1,19 @@
1
1
  /** Parse a `--limit`/`--interval`-style flag into a positive integer, or undefined when absent. */
2
2
  export declare function readPositiveInt(value: string | undefined): number | undefined;
3
+ /**
4
+ * Parse an `--offset`-style flag into a NON-NEGATIVE integer, or undefined when absent.
5
+ *
6
+ * Deliberately separate from `readPositiveInt`: for `--limit`/`--interval`, zero is
7
+ * meaningless and rejecting it is correct, but for an offset zero is the natural
8
+ * first page. Sharing one reader made `tables query --offset 0` fail with
9
+ * "Expected a positive integer." — the identity case of the very flag whose help
10
+ * text says "Skip this many rows" (OXY-4360).
11
+ *
12
+ * Callers must test the result with `!== undefined`, never for truthiness: a valid
13
+ * 0 is falsy, which is how the same flag then went on to be dropped from the
14
+ * request body it had just been validated for.
15
+ */
16
+ export declare function readNonNegativeInt(value: string | undefined): number | undefined;
3
17
  /** Read a string field from an unknown record-shaped value, or null when it is missing/non-string. */
4
18
  export declare function readRecordString(value: unknown, key: string): string | null;
5
19
  /**
@@ -20,6 +20,32 @@ export function readPositiveInt(value) {
20
20
  }
21
21
  return parsed;
22
22
  }
23
+ /**
24
+ * Parse an `--offset`-style flag into a NON-NEGATIVE integer, or undefined when absent.
25
+ *
26
+ * Deliberately separate from `readPositiveInt`: for `--limit`/`--interval`, zero is
27
+ * meaningless and rejecting it is correct, but for an offset zero is the natural
28
+ * first page. Sharing one reader made `tables query --offset 0` fail with
29
+ * "Expected a positive integer." — the identity case of the very flag whose help
30
+ * text says "Skip this many rows" (OXY-4360).
31
+ *
32
+ * Callers must test the result with `!== undefined`, never for truthiness: a valid
33
+ * 0 is falsy, which is how the same flag then went on to be dropped from the
34
+ * request body it had just been validated for.
35
+ */
36
+ export function readNonNegativeInt(value) {
37
+ const trimmed = value?.trim();
38
+ if (!trimmed)
39
+ return undefined;
40
+ const parsed = Number(trimmed);
41
+ if (!Number.isSafeInteger(parsed) || parsed < 0) {
42
+ throw new OxygenError("invalid_number", "Expected a non-negative integer.", {
43
+ details: { value },
44
+ exitCode: 1,
45
+ });
46
+ }
47
+ return parsed;
48
+ }
23
49
  /** Read a string field from an unknown record-shaped value, or null when it is missing/non-string. */
24
50
  export function readRecordString(value, key) {
25
51
  if (!value || typeof value !== "object" || Array.isArray(value))
@@ -84,9 +84,20 @@ const MUTATING_COMMANDS = new Set([
84
84
  "mailboxes warmup reconnect",
85
85
  ]);
86
86
  // `--approved` usually identifies a paid or externally mutating execution
87
- // mode, but a small number of destructive local operations are explicitly
87
+ // mode, but a small number of approved operations are explicitly
88
88
  // zero-credit. Keep those exceptions exact so discovery never invents spend.
89
89
  const ZERO_CREDIT_APPROVAL_COMMANDS = new Set([
90
+ "tables watcher preview",
91
+ "knowledge repositories connect",
92
+ "knowledge repositories resolve",
93
+ // Creator invitation emails need exact send authorization but cost 0 credits.
94
+ "ugc creators invite",
95
+ "ugc creators send-invite",
96
+ // These approvals record an observed outcome or stop future renewal;
97
+ // neither operation buys a service or consumes Oxygen credits.
98
+ "ugc amplification reconcile",
99
+ "ugc peer-amplification reconcile",
100
+ "ugc sponsorship cancel",
90
101
  // A Function binding stores a cap for future runs; creating it executes nothing.
91
102
  "functions bind",
92
103
  // Starting an attended session itself is free. This legacy compatibility
@@ -94,6 +105,9 @@ const ZERO_CREDIT_APPROVAL_COMMANDS = new Set([
94
105
  // trigger the billed model loop.
95
106
  "copilot start",
96
107
  "mailboxes delete",
108
+ // Previews without --approved; with it, removes a program no creator ever
109
+ // joined. No provider call, no credits.
110
+ "ugc programs delete",
97
111
  // This approval only reopens exact fingerprint-bound tenant rows. It never
98
112
  // calls the provider, dispatches an action, or touches the credit ledger.
99
113
  "sequences recover-capacity",
@@ -108,14 +122,27 @@ const ZERO_CREDIT_APPROVAL_COMMANDS = new Set([
108
122
  // Exact noun-style reads whose leaf happens to look like a mutating verb.
109
123
  // `workflows run <id>` gets an existing Workflow run; `workflows call` creates
110
124
  // one. Keep the exception exact so genuine `run` actions remain mutations.
111
- const READ_ONLY_COMMANDS = new Set(["workflows run"]);
125
+ const READ_ONLY_COMMANDS = new Set([
126
+ "workflows run",
127
+ // Inspect existing creator receipts; never generate or import again.
128
+ "ugc posts draft-status",
129
+ "ugc posts history",
130
+ ]);
112
131
  // Exact commands whose execution fence is not named `--live`. A bare
113
132
  // invocation still previews, so machine-readable discovery must not imply that
114
133
  // calling the command without its confirmation flag writes anything.
115
134
  const PREVIEW_BY_DEFAULT_COMMANDS = new Set([
135
+ "tables watcher preview",
136
+ "ugc creators invite",
137
+ "ugc creators send-invite",
116
138
  "ugc posts draft",
139
+ "ugc programs delete",
117
140
  "ugc voice import",
118
141
  "ugc sponsorship preview",
142
+ "ugc sponsorship cancel",
143
+ "ugc amplification reconcile",
144
+ "ugc peer-amplification reconcile",
145
+ "ugc peer-amplification save",
119
146
  // Fenced by --approved, not --live: a bare call resolves the sender, sequence,
120
147
  // audience and caps and writes nothing. Without this entry discovery would tell
121
148
  // an agent that previewing the play arms it, and the preview would go unrun.
@@ -127,6 +154,7 @@ const PREVIEW_BY_DEFAULT_COMMANDS = new Set([
127
154
  "support admin reply",
128
155
  // A bare call reads the Plain workspace and prints the plan; --apply writes.
129
156
  "support admin setup",
157
+ "verify email",
130
158
  "workflows webhooks rotate",
131
159
  ]);
132
160
  export function buildCommandManifest(program, binaryName) {
@@ -4,7 +4,7 @@ import { requestOxygen } from "./http-client.js";
4
4
  export function registerFunctionsCommands(program, handle) {
5
5
  const functions = program.command("functions")
6
6
  .description("Create, edit, publish and reuse Functions backed by ordinary Tables.")
7
- .addHelpText("after", "\nDraft edits are isolated. Publishing updates future invocations of every caller; queued, in-flight and past runs retain their captured version. Existing caller caps never increase automatically.\nFlow: draft → describe → publish → bind → columns run --dry-run → approved run → runs.\n");
7
+ .addHelpText("after", "\nDraft edits are isolated. Publishing updates future invocations of every caller; queued, in-flight and past runs retain their captured version. Existing caller caps never increase automatically.\nFlow: draft → describe → publish → bind → columns run --dry-run → approved run → runs.\nA bound Function executes on its own published execution table and writes named outputs back to the calling table. The call stays visible from the caller: `table-runs list --table <caller> --status all` lists the run, and the binding column's cell holds the outcome (status, outputs, credits, invocation and run ids). Address a Function by id, slug, or the display name shown by `functions list`.\nWorked example with commands: `oxygen skills install --skill oxygen-gtm --project`, then read its recipes/callable-tables.md.\n");
8
8
  functions.command("list").description("List the Function library, including draft and disabled Functions (up to 500).")
9
9
  .option("--json", "Print a JSON envelope.")
10
10
  .action((options) => handle("functions list", options, () => requestOxygen("/api/cli/functions")));
@@ -21,16 +21,24 @@ export function registerFunctionsCommands(program, handle) {
21
21
  function: ref,
22
22
  ...(options.expectedDraftHash ? { expected_draft_hash: options.expectedDraftHash } : {}),
23
23
  } })));
24
- functions.command("publish <function>").description("Publish the inspected draft for every caller's future invocations; preserves captured runs and caller caps.")
24
+ functions.command("publish <function>").description("Publish the inspected draft for every caller's future invocations; preserves captured runs and caller caps. Until the first publish a draft is addressed by its backing table id; publishing mints the Function id that bindings and runs record, and the table id keeps resolving.")
25
25
  .requiredOption("--expected-draft-hash <hash>", "function.draft.contentHash returned by draft or describe; rejects concurrent edits.")
26
26
  .option("--json", "Print a JSON envelope.")
27
27
  .action((ref, options) => handle("functions publish", options, () => requestOxygen("/api/cli/functions", { method: "POST", body: { operation: "publish", function: ref, expected_draft_hash: options.expectedDraftHash } })));
28
- functions.command("runs <function>").description("Inspect a Function's latest 100 invocations and their captured versions.")
28
+ functions.command("runs <function>").description("Inspect a Function's latest 100 invocations, the table that called each one, and their captured versions. For a call that did not complete, creditsUsed can show the estimate; `table-runs provider-summary <run_id>` reports the credits actually captured.")
29
29
  .option("--json", "Print a JSON envelope.")
30
30
  .action((ref, options) => handle("functions runs", options, () => requestOxygen(`/api/cli/functions/runs?${new URLSearchParams({ function: ref })}`)));
31
- functions.command("bind <table> <function>").description("Add a Function column with explicit input/output mappings and a caller credit cap.")
31
+ functions.command("rename <function> <name>").description("Rename a Function while preserving its identity, callers and published execution.")
32
+ .option("--json", "Print a JSON envelope.")
33
+ .action((ref, name, options) => handle("functions rename", options, () => requestOxygen("/api/cli/functions", { method: "POST", body: { operation: "rename", function: ref, display_name: name } })));
34
+ functions.command("delete <function>").description("Preview removal from the Function library; preserves backing tables, rows and run history. Connected callers or active runs block deletion.")
35
+ .addHelpText("after", "\nDeletion is final: there is no restore, unlike `tables delete`. To reuse the logic, `tables duplicate` the backing Table and draft a new Function from the copy.\n")
36
+ .option("--yes", "Confirm removal of this Function after reviewing its callers.")
37
+ .option("--json", "Print a JSON envelope.")
38
+ .action((ref, options) => handle("functions delete", options, () => requestOxygen("/api/cli/functions", { method: "POST", body: { operation: "delete", function: ref, approved: options.yes === true } })));
39
+ functions.command("bind <table> <function>").description("Add a Function column with explicit input/output mappings and a caller credit cap. Create each mapped output column on the caller table first with `columns add`; bind rejects an output mapped to a column the caller table does not have.")
32
40
  .requiredOption("--inputs-json <json>", "Object mapping Function input keys to caller column keys.")
33
- .requiredOption("--outputs-json <json>", "Object mapping Function output keys to caller column keys.")
41
+ .requiredOption("--outputs-json <json>", "Object mapping Function output keys to existing caller column keys.")
34
42
  .requiredOption("--max-credits-per-item <n>", "Hard credit ceiling for each caller row; future publishes cannot raise it.")
35
43
  .option("--overwrite-policy <policy>", "Callback writes: empty_only or overwrite.", "empty_only")
36
44
  .option("--key <key>", "Function column key.").option("--label <label>", "Function column label.")
package/dist/help.js CHANGED
@@ -137,8 +137,10 @@ export function applyOxygenHelp(program, binaryName) {
137
137
  // OXYGEN_API_KEY never runs it — without this step nothing on any
138
138
  // first-touch surface names the skill that teaches the GTM loops.
139
139
  ` 2. ${binaryName} skills install --json load the skills that teach the GTM loops (automatic after login)`,
140
+ " Add --project to keep the skills inside the current project, including confined agent sessions.",
140
141
  ` 3. ${binaryName} context resolve --json load workspace context before operating primitives`,
141
142
  ` 4. ${binaryName} capabilities search "<goal>" --json route the goal, then hydrate one exact command`,
143
+ ` ${binaryName} commands search "<term>" --json find a command by name or purpose instead of dumping the manifest`,
142
144
  ` 5. ${binaryName} recipes list --json choose a play from the Recipe catalog for your goal`,
143
145
  ` Provider inventory: ${binaryName} tools search <brand> --json, then ${binaryName} tools search --provider <provider-id> --all --json (Blitz uses blitzapi).`,
144
146
  ` Installable systems and recurring monitors: ${binaryName} blueprints list --json.`,