@oxygen-agent/cli 1.275.1 → 1.284.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.
- package/README.md +1 -1
- package/dist/command-manifest.d.ts +30 -0
- package/dist/command-manifest.js +70 -0
- package/dist/help.d.ts +2 -0
- package/dist/help.js +79 -0
- package/dist/http-client.d.ts +1 -0
- package/dist/http-client.js +13 -0
- package/dist/index.js +388 -24
- package/dist/knowledge-mirror.d.ts +22 -0
- package/dist/knowledge-mirror.js +56 -0
- package/node_modules/@oxygen/shared/dist/billing.d.ts +2 -0
- package/node_modules/@oxygen/shared/dist/billing.js +6 -0
- package/node_modules/@oxygen/shared/dist/cli-result.d.ts +3 -0
- package/node_modules/@oxygen/shared/dist/cli-result.js +65 -0
- package/node_modules/@oxygen/shared/dist/deprecation-registry.d.ts +12 -0
- package/node_modules/@oxygen/shared/dist/deprecation-registry.js +58 -0
- package/node_modules/@oxygen/shared/dist/knowledge-markdown.d.ts +25 -0
- package/node_modules/@oxygen/shared/dist/knowledge-markdown.js +74 -0
- package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
- package/node_modules/@oxygen/shared/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
export type CommandManifestFlag = {
|
|
3
|
+
flags: string;
|
|
4
|
+
description: string;
|
|
5
|
+
required: boolean;
|
|
6
|
+
};
|
|
7
|
+
export type CommandManifestArgument = {
|
|
8
|
+
name: string;
|
|
9
|
+
required: boolean;
|
|
10
|
+
description: string;
|
|
11
|
+
};
|
|
12
|
+
export type CommandManifestEntry = {
|
|
13
|
+
name: string;
|
|
14
|
+
group: string;
|
|
15
|
+
description: string;
|
|
16
|
+
arguments: CommandManifestArgument[];
|
|
17
|
+
flags: CommandManifestFlag[];
|
|
18
|
+
spends_credits: boolean;
|
|
19
|
+
mutates: boolean;
|
|
20
|
+
json_supported: boolean;
|
|
21
|
+
hidden: boolean;
|
|
22
|
+
};
|
|
23
|
+
export type CommandManifest = {
|
|
24
|
+
binary: string;
|
|
25
|
+
version: string;
|
|
26
|
+
total: number;
|
|
27
|
+
exit_codes: Record<string, string>;
|
|
28
|
+
commands: CommandManifestEntry[];
|
|
29
|
+
};
|
|
30
|
+
export declare function buildCommandManifest(program: Command, binaryName: string): CommandManifest;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { CLI_EXIT_CODE_TABLE, OXYGEN_VERSION } from "@oxygen/shared";
|
|
2
|
+
const MUTATING_VERBS = new Set([
|
|
3
|
+
"add", "apply", "approve", "archive", "assign", "buy", "cancel", "clear",
|
|
4
|
+
"configure", "connect", "create", "delete", "disable", "dispatch", "draft",
|
|
5
|
+
"emit", "enable", "enroll", "grant", "import", "insert", "invite", "launch",
|
|
6
|
+
"login", "logout", "materialize", "merge", "migrate", "order", "pause",
|
|
7
|
+
"publish", "purchase", "push", "record", "register", "remove", "rename",
|
|
8
|
+
"reorder", "reply", "rerun", "reset", "resolve", "restore", "resume",
|
|
9
|
+
"retry", "retype", "revoke", "rotate", "run", "save", "schedule", "select",
|
|
10
|
+
"send", "set", "share", "start", "stop", "subscribe", "sync", "unpublish",
|
|
11
|
+
"unshare", "unsubscribe", "update", "upload", "upsert", "use", "withdraw",
|
|
12
|
+
"write",
|
|
13
|
+
]);
|
|
14
|
+
export function buildCommandManifest(program, binaryName) {
|
|
15
|
+
const commands = [];
|
|
16
|
+
for (const child of program.commands) {
|
|
17
|
+
collectCommand(child, [], commands);
|
|
18
|
+
}
|
|
19
|
+
commands.sort((a, b) => a.name.localeCompare(b.name));
|
|
20
|
+
return {
|
|
21
|
+
binary: binaryName,
|
|
22
|
+
version: OXYGEN_VERSION,
|
|
23
|
+
total: commands.length,
|
|
24
|
+
exit_codes: Object.fromEntries(Object.entries(CLI_EXIT_CODE_TABLE).map(([code, meaning]) => [code, meaning])),
|
|
25
|
+
commands,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function collectCommand(command, ancestors, out) {
|
|
29
|
+
const path = [...ancestors, command.name()];
|
|
30
|
+
const children = command.commands;
|
|
31
|
+
// Group commands (e.g. `oxygen tables`) exist to hold subcommands; only leaf
|
|
32
|
+
// commands are invocable work, so only leaves become manifest entries.
|
|
33
|
+
if (children.length === 0) {
|
|
34
|
+
out.push(toManifestEntry(command, path));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
for (const child of children) {
|
|
38
|
+
collectCommand(child, path, out);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function toManifestEntry(command, path) {
|
|
42
|
+
const options = command.options.filter((option) => !option.hidden);
|
|
43
|
+
const flagStrings = options.map((option) => option.flags);
|
|
44
|
+
const leafVerb = path[path.length - 1] ?? "";
|
|
45
|
+
const verbPrefix = leafVerb.split("-")[0] ?? leafVerb;
|
|
46
|
+
return {
|
|
47
|
+
name: path.join(" "),
|
|
48
|
+
group: path[0] ?? "",
|
|
49
|
+
description: command.description(),
|
|
50
|
+
arguments: command.registeredArguments.map((argument) => ({
|
|
51
|
+
name: argument.name(),
|
|
52
|
+
required: argument.required,
|
|
53
|
+
description: argument.description,
|
|
54
|
+
})),
|
|
55
|
+
flags: options.map((option) => ({
|
|
56
|
+
flags: option.flags,
|
|
57
|
+
description: option.description,
|
|
58
|
+
required: option.mandatory,
|
|
59
|
+
})),
|
|
60
|
+
spends_credits: flagStrings.some((flags) => flags.includes("--approved") || flags.includes("--max-credits")),
|
|
61
|
+
mutates: MUTATING_VERBS.has(leafVerb) || MUTATING_VERBS.has(verbPrefix),
|
|
62
|
+
json_supported: flagStrings.some((flags) => flags.includes("--json")),
|
|
63
|
+
hidden: isHiddenCommand(command),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function isHiddenCommand(command) {
|
|
67
|
+
// Commander keeps hidden state private; read it defensively so a library
|
|
68
|
+
// bump degrades to hidden:false instead of a crash.
|
|
69
|
+
return Boolean(command._hidden);
|
|
70
|
+
}
|
package/dist/help.d.ts
ADDED
package/dist/help.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { CLI_EXIT_CODE_TABLE } from "@oxygen/shared";
|
|
2
|
+
// Grouped `--help` for the ~70 top-level command groups: commander's default
|
|
3
|
+
// registration-order wall (login, auth, profiles, ... before any GTM noun) is
|
|
4
|
+
// the first thing every fresh agent reads, so order it by the OXYGEN OS layer
|
|
5
|
+
// a command belongs to and close with an agent quickstart + the reserved
|
|
6
|
+
// exit-code table. Commands missing from the map land in the last group so a
|
|
7
|
+
// new command never disappears from help.
|
|
8
|
+
const HELP_GROUPS = [
|
|
9
|
+
{
|
|
10
|
+
heading: "Get started & account:",
|
|
11
|
+
commands: [
|
|
12
|
+
"login", "auth", "profiles", "logout", "update", "api-keys", "whoami",
|
|
13
|
+
"onboarding", "status", "orgs", "commands", "skills", "session",
|
|
14
|
+
"support", "feedback",
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
heading: "Knowledge (context, wiki, recipes):",
|
|
19
|
+
commands: ["context", "knowledge", "prompts", "templates", "blueprints"],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
heading: "Data (tables, CRM, dashboards):",
|
|
23
|
+
commands: [
|
|
24
|
+
"tables", "rows", "cells", "columns", "action-column", "enrich-column",
|
|
25
|
+
"enrichment", "table-runs", "table-ingestions", "runs", "crm",
|
|
26
|
+
"dashboards", "projects", "signup-leads",
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
heading: "Sourcing & search:",
|
|
31
|
+
commands: ["sourcing", "lead-sourcing", "search", "companies", "people", "find", "tools"],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
heading: "Outbound & channels:",
|
|
35
|
+
commands: [
|
|
36
|
+
"sequences", "senders", "inbox", "messages", "mailboxes",
|
|
37
|
+
"managed-inboxes", "deliverability", "domains", "email", "schedules",
|
|
38
|
+
"suppressions", "egress", "linkedin", "connections", "followers",
|
|
39
|
+
"viewers", "posts", "engagement", "whatsapp", "publishing", "notetaker",
|
|
40
|
+
"reviews",
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
heading: "Automation, billing & admin:",
|
|
45
|
+
commands: [
|
|
46
|
+
"workflows", "integrations", "custom-integrations", "billing", "budget",
|
|
47
|
+
"observability", "worker", "db", "admin", "directory",
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
const FALLBACK_HEADING = "Other commands:";
|
|
52
|
+
export function applyOxygenHelp(program, binaryName) {
|
|
53
|
+
const headingByCommand = new Map();
|
|
54
|
+
for (const group of HELP_GROUPS) {
|
|
55
|
+
for (const name of group.commands)
|
|
56
|
+
headingByCommand.set(name, group.heading);
|
|
57
|
+
}
|
|
58
|
+
for (const command of program.commands) {
|
|
59
|
+
command.helpGroup(headingByCommand.get(command.name()) ?? FALLBACK_HEADING);
|
|
60
|
+
}
|
|
61
|
+
const exitCodeLine = Object.entries(CLI_EXIT_CODE_TABLE)
|
|
62
|
+
.map(([code, meaning]) => `${code} ${meaning.split(" (")[0]}`)
|
|
63
|
+
.join(" · ");
|
|
64
|
+
program.addHelpText("afterAll", [
|
|
65
|
+
"",
|
|
66
|
+
"Agent quickstart:",
|
|
67
|
+
` 1. ${binaryName} login connect this terminal (or set OXYGEN_API_KEY)`,
|
|
68
|
+
` 2. ${binaryName} onboarding start --json load workspace context + the skill that teaches the GTM loops`,
|
|
69
|
+
` 3. ${binaryName} commands --json full machine-readable command grammar (this CLI's self-index)`,
|
|
70
|
+
"",
|
|
71
|
+
"Conventions:",
|
|
72
|
+
" --json prints a stable envelope {ok, data|error, meta}; errors always print it.",
|
|
73
|
+
" Commands that spend credits or write to external platforms are gated: live runs",
|
|
74
|
+
" require --approved --max-credits <n> and fail with a typed error until approved.",
|
|
75
|
+
" State-changing responses include a web_url deep-link to inspect the result.",
|
|
76
|
+
"",
|
|
77
|
+
`Exit codes: ${exitCodeLine}`,
|
|
78
|
+
].join("\n"));
|
|
79
|
+
}
|
package/dist/http-client.d.ts
CHANGED
package/dist/http-client.js
CHANGED
|
@@ -42,6 +42,17 @@ path, options = {}) {
|
|
|
42
42
|
if (options.body) {
|
|
43
43
|
headers["Content-Type"] = "application/json";
|
|
44
44
|
}
|
|
45
|
+
// Every mutating request carries an idempotency key. Routes that support
|
|
46
|
+
// replay dedupe on it; others ignore the header. On a timeout the key is
|
|
47
|
+
// echoed in error details so a re-run (OXYGEN_IDEMPOTENCY_KEY=<key>) can
|
|
48
|
+
// retry without duplicating the write once the route supports replay.
|
|
49
|
+
const method = options.method ?? "GET";
|
|
50
|
+
const idempotencyKey = method === "GET"
|
|
51
|
+
? undefined
|
|
52
|
+
: options.idempotencyKey ?? process.env.OXYGEN_IDEMPOTENCY_KEY ?? randomUUID();
|
|
53
|
+
if (idempotencyKey) {
|
|
54
|
+
headers["Idempotency-Key"] = idempotencyKey;
|
|
55
|
+
}
|
|
45
56
|
let response;
|
|
46
57
|
const timeoutMs = resolveRequestTimeoutMs(options.timeoutMs);
|
|
47
58
|
const timeout = createTimeoutSignal(timeoutMs);
|
|
@@ -64,6 +75,7 @@ path, options = {}) {
|
|
|
64
75
|
path,
|
|
65
76
|
timeout_ms: timeoutMs,
|
|
66
77
|
trace_id: traceId,
|
|
78
|
+
...(idempotencyKey ? { idempotency_key: idempotencyKey } : {}),
|
|
67
79
|
},
|
|
68
80
|
exitCode: 1,
|
|
69
81
|
});
|
|
@@ -72,6 +84,7 @@ path, options = {}) {
|
|
|
72
84
|
details: {
|
|
73
85
|
api_url: apiUrl,
|
|
74
86
|
reason: error instanceof Error ? error.message : "unknown",
|
|
87
|
+
...(idempotencyKey ? { idempotency_key: idempotencyKey } : {}),
|
|
75
88
|
},
|
|
76
89
|
exitCode: 1,
|
|
77
90
|
});
|