ethos-cli 0.1.0
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 +121 -0
- package/dist/bin/ethos.d.ts +4 -0
- package/dist/bin/ethos.js +45 -0
- package/dist/bin/ethos.js.map +1 -0
- package/dist/commands/agents.d.ts +2 -0
- package/dist/commands/agents.js +162 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.js +180 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/skills.d.ts +2 -0
- package/dist/commands/skills.js +90 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/tables.d.ts +17 -0
- package/dist/commands/tables.js +534 -0
- package/dist/commands/tables.js.map +1 -0
- package/dist/lib/auth-store.d.ts +13 -0
- package/dist/lib/auth-store.js +47 -0
- package/dist/lib/auth-store.js.map +1 -0
- package/dist/lib/client.d.ts +19 -0
- package/dist/lib/client.js +69 -0
- package/dist/lib/client.js.map +1 -0
- package/dist/lib/command-helpers.d.ts +8 -0
- package/dist/lib/command-helpers.js +24 -0
- package/dist/lib/command-helpers.js.map +1 -0
- package/dist/lib/config.d.ts +12 -0
- package/dist/lib/config.js +38 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/output.d.ts +7 -0
- package/dist/lib/output.js +23 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/table-types.d.ts +138 -0
- package/dist/lib/table-types.js +2 -0
- package/dist/lib/table-types.js.map +1 -0
- package/dist/scripts/install-skills.d.ts +1 -0
- package/dist/scripts/install-skills.js +44 -0
- package/dist/scripts/install-skills.js.map +1 -0
- package/dist/skills-installer/agents.d.ts +9 -0
- package/dist/skills-installer/agents.js +31 -0
- package/dist/skills-installer/agents.js.map +1 -0
- package/dist/skills-installer/index.d.ts +4 -0
- package/dist/skills-installer/index.js +5 -0
- package/dist/skills-installer/index.js.map +1 -0
- package/dist/skills-installer/install.d.ts +15 -0
- package/dist/skills-installer/install.js +82 -0
- package/dist/skills-installer/install.js.map +1 -0
- package/dist/skills-installer/lockfile.d.ts +17 -0
- package/dist/skills-installer/lockfile.js +23 -0
- package/dist/skills-installer/lockfile.js.map +1 -0
- package/dist/skills-installer/skill.d.ts +9 -0
- package/dist/skills-installer/skill.js +70 -0
- package/dist/skills-installer/skill.js.map +1 -0
- package/package.json +48 -0
- package/postinstall.cjs +23 -0
- package/skills/find-people-at-companies.md +111 -0
package/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Ethos CLI
|
|
2
|
+
|
|
3
|
+
Commander-based CLI for Ethos agent and table operations.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g ethos-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Auth
|
|
12
|
+
|
|
13
|
+
The CLI can connect through your existing browser session:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
ethos auth login
|
|
17
|
+
ethos auth status
|
|
18
|
+
ethos auth logout
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Use `--app-url` if your frontend is not on the default local/prod URL:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
ethos --api-url http://127.0.0.1:8001 auth login --app-url http://localhost:3001
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
You can also configure auth with flags or environment variables:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
export ETHOS_API_URL="https://api.ethos.hello-cluster.com"
|
|
31
|
+
export ETHOS_API_KEY="..."
|
|
32
|
+
export ETHOS_ORG_ID="..."
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Every command also accepts `--api-url`, `--api-key`, `--access-token`, `--org-id`, and `--json`.
|
|
36
|
+
|
|
37
|
+
## Bundled Skills
|
|
38
|
+
|
|
39
|
+
Installing the CLI also installs bundled Ethos skills into supported local agents
|
|
40
|
+
when they are detected: Claude Code, Codex, and Cursor.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
ethos skills install
|
|
44
|
+
ethos skills install --agents codex
|
|
45
|
+
ethos skills list
|
|
46
|
+
ethos skills remove
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Set `ETHOS_SKIP_SKILLS=1` before install to skip the automatic postinstall sync.
|
|
50
|
+
|
|
51
|
+
## Agent Commands
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
ethos agents list
|
|
55
|
+
ethos agents get <agent-id>
|
|
56
|
+
|
|
57
|
+
ethos agents create \
|
|
58
|
+
--name "Company enricher" \
|
|
59
|
+
--instructions "Enrich this company from the row context" \
|
|
60
|
+
--workflow-type company_enrichment \
|
|
61
|
+
--ability web-search \
|
|
62
|
+
--ability linkedin-company-lookup \
|
|
63
|
+
--tool-preset browser
|
|
64
|
+
|
|
65
|
+
ethos agents configure <agent-id> --workflow-type people_sourcing --clear-abilities
|
|
66
|
+
ethos agents delete <agent-id>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Workflow/table compatibility is shown in `--help`: company tables support company enrichment columns and people sourcing, people tables support person enrichment columns. The CLI sends the configured request and lets backend validation decide the final result.
|
|
70
|
+
|
|
71
|
+
## Table Commands
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
ethos tables list
|
|
75
|
+
ethos tables get <table-id>
|
|
76
|
+
ethos tables import-csv ./companies.csv --entity-type company
|
|
77
|
+
ethos tables import-csv ./people.csv --entity-type people
|
|
78
|
+
|
|
79
|
+
ethos tables views list <table-id>
|
|
80
|
+
ethos tables views create <table-id> --name "Qualified companies" --filter <column-id>:contains:example
|
|
81
|
+
ethos tables views configure <table-id> <view-id> --clear-filters
|
|
82
|
+
ethos tables views delete <table-id> <view-id>
|
|
83
|
+
|
|
84
|
+
ethos tables columns create-agent <table-id> \
|
|
85
|
+
--name "ICP fit" \
|
|
86
|
+
--agent-id <agent-id> \
|
|
87
|
+
--prompt "Score this account" \
|
|
88
|
+
--output-field score \
|
|
89
|
+
--output-field reason
|
|
90
|
+
|
|
91
|
+
ethos tables columns configure <table-id> <column-id> --name "New name"
|
|
92
|
+
ethos tables columns delete <table-id> <column-id>
|
|
93
|
+
ethos tables columns extract-json <table-id> <column-id>
|
|
94
|
+
|
|
95
|
+
ethos tables rows delete <table-id> <row-id>
|
|
96
|
+
ethos tables rows delete <table-id> 3 --by-index
|
|
97
|
+
ethos tables rows delete <table-id> 1 2 3 --by-index
|
|
98
|
+
|
|
99
|
+
ethos tables agent-edits apply <table-id> \
|
|
100
|
+
--instruction "Delete rows that are no longer relevant" \
|
|
101
|
+
--row-id <focused-row-id>
|
|
102
|
+
|
|
103
|
+
ethos tables cells set <table-id> <row-id> <column-id> --value "Manual note"
|
|
104
|
+
ethos tables cells set <table-id> <row-id> <column-id> --value '{"score":9}' --value-json
|
|
105
|
+
|
|
106
|
+
ethos tables runs start <table-id> <column-id> --scope first_5
|
|
107
|
+
ethos tables runs get <run-id>
|
|
108
|
+
ethos tables runs interrupt <run-id>
|
|
109
|
+
|
|
110
|
+
ethos tables source-people <company-table-id> \
|
|
111
|
+
--view-id <view-id> \
|
|
112
|
+
--agent-id <people-sourcing-agent-id> \
|
|
113
|
+
--input-column <company-domain-column-id> \
|
|
114
|
+
--targeting-brief "Find funding and finance contacts" \
|
|
115
|
+
--created-by-codex
|
|
116
|
+
|
|
117
|
+
ethos tables runs create-people-table <run-id>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
When stdout is not a TTY, output is JSON by default so coding agents can parse it reliably.
|
|
121
|
+
Table-detail commands such as `tables get`, `tables import-csv`, and `tables runs create-people-table` include top-level `table_id`, `column_ids`, `row_ids`, and `view_ids` in addition to the full nested objects. `tables source-people` includes top-level `table_id`, `column_id`, and `run_id`.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { registerAgents } from "../commands/agents.js";
|
|
7
|
+
import { registerAuth } from "../commands/auth.js";
|
|
8
|
+
import { registerSkills } from "../commands/skills.js";
|
|
9
|
+
import { registerTables } from "../commands/tables.js";
|
|
10
|
+
import { addGlobalOptions } from "../lib/config.js";
|
|
11
|
+
import { printError } from "../lib/output.js";
|
|
12
|
+
const pkg = createRequire(import.meta.url)("../../package.json");
|
|
13
|
+
export function createEthosProgram() {
|
|
14
|
+
const program = new Command();
|
|
15
|
+
addGlobalOptions(program
|
|
16
|
+
.name("ethos")
|
|
17
|
+
.description("CLI for Ethos workspace and table operations")
|
|
18
|
+
.version(pkg.version));
|
|
19
|
+
registerAuth(program);
|
|
20
|
+
registerAgents(program);
|
|
21
|
+
registerSkills(program);
|
|
22
|
+
registerTables(program);
|
|
23
|
+
return program;
|
|
24
|
+
}
|
|
25
|
+
export async function main(argv = process.argv) {
|
|
26
|
+
await createEthosProgram().parseAsync(argv);
|
|
27
|
+
}
|
|
28
|
+
function isDirectInvocation() {
|
|
29
|
+
const entry = process.argv[1];
|
|
30
|
+
if (!entry)
|
|
31
|
+
return false;
|
|
32
|
+
try {
|
|
33
|
+
return realpathSync(fileURLToPath(import.meta.url)) === realpathSync(entry);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (isDirectInvocation()) {
|
|
40
|
+
main().catch((error) => {
|
|
41
|
+
printError(error);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=ethos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ethos.js","sourceRoot":"","sources":["../../src/bin/ethos.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAAwB,CAAC;AAExF,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,gBAAgB,CACd,OAAO;SACJ,IAAI,CAAC,OAAO,CAAC;SACb,WAAW,CAAC,8CAA8C,CAAC;SAC3D,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CACxB,CAAC;IAEF,YAAY,CAAC,OAAO,CAAC,CAAC;IACtB,cAAc,CAAC,OAAO,CAAC,CAAC;IACxB,cAAc,CAAC,OAAO,CAAC,CAAC;IACxB,cAAc,CAAC,OAAO,CAAC,CAAC;IACxB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAAiB,OAAO,CAAC,IAAI;IACtD,MAAM,kBAAkB,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,YAAY,CAAC,KAAK,CAAC,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,kBAAkB,EAAE,EAAE,CAAC;IACzB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACrB,UAAU,CAAC,KAAK,CAAC,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { collect, compactObject, jsonRequest, pathId, withClient } from "../lib/command-helpers.js";
|
|
2
|
+
import { printResult } from "../lib/output.js";
|
|
3
|
+
const workflowTypes = new Set([
|
|
4
|
+
"company_enrichment",
|
|
5
|
+
"person_enrichment",
|
|
6
|
+
"people_sourcing",
|
|
7
|
+
]);
|
|
8
|
+
const abilities = new Set([
|
|
9
|
+
"web-search",
|
|
10
|
+
"web-fetch",
|
|
11
|
+
"browser-use",
|
|
12
|
+
"ethos-hub",
|
|
13
|
+
"linkedin-profile-lookup",
|
|
14
|
+
"linkedin-company-lookup",
|
|
15
|
+
]);
|
|
16
|
+
const toolPresets = new Set(["filesystem", "shell", "browser"]);
|
|
17
|
+
const compatibilityHelp = `
|
|
18
|
+
|
|
19
|
+
Workflow/table compatibility:
|
|
20
|
+
company_enrichment agents are intended for company table agent columns.
|
|
21
|
+
person_enrichment agents are intended for people table agent columns.
|
|
22
|
+
people_sourcing agents are intended for company tables via "ethos tables source-people".
|
|
23
|
+
The CLI sends the request as configured; backend validation is the source of truth.`;
|
|
24
|
+
export function registerAgents(program) {
|
|
25
|
+
const agents = program.command("agents").alias("agent").description("Manage Ethos agents").addHelpText("after", compatibilityHelp);
|
|
26
|
+
const listCommand = agents.command("list").description("List agents");
|
|
27
|
+
listCommand.action(async () => {
|
|
28
|
+
await withClient(listCommand, async (client, config) => {
|
|
29
|
+
printResult(config, await client.request("/v1/agents"));
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
const getCommand = agents.command("get <agent-id>").description("Fetch an agent");
|
|
33
|
+
getCommand.action(async (agentId) => {
|
|
34
|
+
await withClient(getCommand, async (client, config) => {
|
|
35
|
+
printResult(config, await client.request(`/v1/agents/${pathId(agentId)}`));
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
const createCommand = addAgentOptions(agents
|
|
39
|
+
.command("create")
|
|
40
|
+
.description("Create an agent with workflow type, abilities, skills, tool presets, and instructions")
|
|
41
|
+
.requiredOption("--name <name>", "agent name")
|
|
42
|
+
.requiredOption("--instructions <instructions>", "full agent instructions prompt"), { includeClearFlags: false, includeCoreFlags: false });
|
|
43
|
+
createCommand.action(async () => {
|
|
44
|
+
await withClient(createCommand, async (client, config) => {
|
|
45
|
+
const options = createCommand.opts();
|
|
46
|
+
const body = compactObject({
|
|
47
|
+
name: options.name,
|
|
48
|
+
description: options.description,
|
|
49
|
+
instructions: options.instructions,
|
|
50
|
+
model: options.model,
|
|
51
|
+
workflow_type: parseWorkflowType(options.workflowType, "--workflow-type"),
|
|
52
|
+
abilities: parseAbilities(options.ability, "--ability"),
|
|
53
|
+
skills: parseStringList(options.skill),
|
|
54
|
+
tool_presets: parseToolPresets(options.toolPreset, "--tool-preset"),
|
|
55
|
+
});
|
|
56
|
+
printResult(config, await client.request("/v1/agents", jsonRequest("POST", body)));
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
const configureCommand = addAgentOptions(agents.command("configure <agent-id>").alias("update").description("Update an agent configuration"), { includeClearFlags: true, includeCoreFlags: true });
|
|
60
|
+
configureCommand.action(async (agentId) => {
|
|
61
|
+
await withClient(configureCommand, async (client, config) => {
|
|
62
|
+
const options = configureCommand.opts();
|
|
63
|
+
const body = compactObject({
|
|
64
|
+
name: options.name,
|
|
65
|
+
description: options.description,
|
|
66
|
+
instructions: options.instructions,
|
|
67
|
+
model: options.model,
|
|
68
|
+
workflow_type: parseUpdateWorkflowType(options),
|
|
69
|
+
abilities: parseUpdateList(options.ability, options.clearAbilities, "--ability", parseAbility),
|
|
70
|
+
skills: parseUpdateStringList(options.skill, options.clearSkills),
|
|
71
|
+
tool_presets: parseUpdateList(options.toolPreset, options.clearToolPresets, "--tool-preset", parseToolPreset),
|
|
72
|
+
});
|
|
73
|
+
if (Object.keys(body).length === 0) {
|
|
74
|
+
throw new Error("Pass at least one agent field to configure.");
|
|
75
|
+
}
|
|
76
|
+
printResult(config, await client.request(`/v1/agents/${pathId(agentId)}`, jsonRequest("PATCH", body)));
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
const deleteCommand = agents.command("delete <agent-id>").description("Delete an agent");
|
|
80
|
+
deleteCommand.action(async (agentId) => {
|
|
81
|
+
await withClient(deleteCommand, async (client, config) => {
|
|
82
|
+
printResult(config, await client.request(`/v1/agents/${pathId(agentId)}`, { method: "DELETE" }));
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function addAgentOptions(command, options) {
|
|
87
|
+
if (options.includeCoreFlags) {
|
|
88
|
+
command.option("--name <name>", "agent name").option("--instructions <instructions>", "full agent instructions prompt");
|
|
89
|
+
}
|
|
90
|
+
command
|
|
91
|
+
.option("--description <description>", "agent description")
|
|
92
|
+
.option("--model <model>", "model name")
|
|
93
|
+
.option("--workflow-type <type>", "company_enrichment, person_enrichment, or people_sourcing")
|
|
94
|
+
.option("--ability <ability>", "agent ability; repeatable", collect, [])
|
|
95
|
+
.option("--skill <skill>", "skill name; repeatable", collect, [])
|
|
96
|
+
.option("--tool-preset <preset>", "filesystem, shell, or browser; repeatable", collect, []);
|
|
97
|
+
if (options.includeClearFlags) {
|
|
98
|
+
command
|
|
99
|
+
.option("--clear-abilities", "replace abilities with an empty list")
|
|
100
|
+
.option("--clear-skills", "replace skills with an empty list")
|
|
101
|
+
.option("--clear-tool-presets", "replace tool presets with an empty list")
|
|
102
|
+
.option("--clear-workflow-type", "set workflow_type to null");
|
|
103
|
+
}
|
|
104
|
+
return command.addHelpText("after", compatibilityHelp);
|
|
105
|
+
}
|
|
106
|
+
function parseWorkflowType(value, option) {
|
|
107
|
+
if (value === undefined)
|
|
108
|
+
return undefined;
|
|
109
|
+
if (workflowTypes.has(value))
|
|
110
|
+
return value;
|
|
111
|
+
throw new Error(`${option} must be one of company_enrichment, person_enrichment, people_sourcing.`);
|
|
112
|
+
}
|
|
113
|
+
function parseUpdateWorkflowType(options) {
|
|
114
|
+
if (options.workflowType !== undefined && options.clearWorkflowType) {
|
|
115
|
+
throw new Error("Use either --workflow-type or --clear-workflow-type, not both.");
|
|
116
|
+
}
|
|
117
|
+
if (options.clearWorkflowType)
|
|
118
|
+
return null;
|
|
119
|
+
return parseWorkflowType(options.workflowType, "--workflow-type");
|
|
120
|
+
}
|
|
121
|
+
function parseAbilities(values, option) {
|
|
122
|
+
return parseOptionalList(values, option, parseAbility);
|
|
123
|
+
}
|
|
124
|
+
function parseToolPresets(values, option) {
|
|
125
|
+
return parseOptionalList(values, option, parseToolPreset);
|
|
126
|
+
}
|
|
127
|
+
function parseStringList(values) {
|
|
128
|
+
const parsed = cleanList(values);
|
|
129
|
+
return parsed.length ? parsed : undefined;
|
|
130
|
+
}
|
|
131
|
+
function parseUpdateStringList(values, clear) {
|
|
132
|
+
if (values?.length && clear)
|
|
133
|
+
throw new Error("Use either repeated values or the matching --clear flag, not both.");
|
|
134
|
+
if (clear)
|
|
135
|
+
return [];
|
|
136
|
+
return parseStringList(values);
|
|
137
|
+
}
|
|
138
|
+
function parseUpdateList(values, clear, option, parser) {
|
|
139
|
+
if (values?.length && clear)
|
|
140
|
+
throw new Error(`Use either ${option} or the matching --clear flag, not both.`);
|
|
141
|
+
if (clear)
|
|
142
|
+
return [];
|
|
143
|
+
return parseOptionalList(values, option, parser);
|
|
144
|
+
}
|
|
145
|
+
function parseOptionalList(values, option, parser) {
|
|
146
|
+
const parsed = cleanList(values).map((value) => parser(value, option));
|
|
147
|
+
return parsed.length ? Array.from(new Set(parsed)) : undefined;
|
|
148
|
+
}
|
|
149
|
+
function parseAbility(value, option) {
|
|
150
|
+
if (abilities.has(value))
|
|
151
|
+
return value;
|
|
152
|
+
throw new Error(`${option} must be one of web-search, web-fetch, browser-use, ethos-hub, linkedin-profile-lookup, linkedin-company-lookup.`);
|
|
153
|
+
}
|
|
154
|
+
function parseToolPreset(value, option) {
|
|
155
|
+
if (toolPresets.has(value))
|
|
156
|
+
return value;
|
|
157
|
+
throw new Error(`${option} must be one of filesystem, shell, browser.`);
|
|
158
|
+
}
|
|
159
|
+
function cleanList(values) {
|
|
160
|
+
return (values || []).map((value) => value.trim()).filter(Boolean);
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { hostname } from "node:os";
|
|
3
|
+
import { authConfigPath, clearStoredAuth, readStoredAuth, writeStoredAuth } from "../lib/auth-store.js";
|
|
4
|
+
import { isJsonMode, resolveApiUrl } from "../lib/config.js";
|
|
5
|
+
import { printResult } from "../lib/output.js";
|
|
6
|
+
export function registerAuth(program) {
|
|
7
|
+
const auth = program.command("auth").description("Authenticate the Ethos CLI");
|
|
8
|
+
const loginCommand = auth
|
|
9
|
+
.command("login")
|
|
10
|
+
.description("Connect the CLI through your browser session")
|
|
11
|
+
.option("--app-url <url>", "Ethos web app URL", process.env.ETHOS_APP_URL)
|
|
12
|
+
.option("--device-name <name>", "display name for this CLI session")
|
|
13
|
+
.option("--no-open", "print the approval URL without opening a browser")
|
|
14
|
+
.option("--timeout <seconds>", "seconds to wait for browser approval", "120");
|
|
15
|
+
loginCommand.action(async () => {
|
|
16
|
+
const apiUrl = resolveApiUrl(loginCommand);
|
|
17
|
+
const options = loginCommand.opts();
|
|
18
|
+
const timeoutSeconds = parseTimeout(options.timeout);
|
|
19
|
+
const deviceName = options.deviceName || `Ethos CLI on ${hostname() || "this machine"}`;
|
|
20
|
+
const appUrl = (options.appUrl || inferAppUrl(apiUrl)).replace(/\/+$/, "");
|
|
21
|
+
const registered = await apiRequest(apiUrl, "/v1/auth/cli/register", {
|
|
22
|
+
method: "POST",
|
|
23
|
+
body: {
|
|
24
|
+
app_url: appUrl,
|
|
25
|
+
device_name: deviceName,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
if (isJsonMode(loginCommand)) {
|
|
29
|
+
process.stdout.write(`${JSON.stringify({ success: true, response: { claim_url: registered.claim_url, expires_at: registered.expires_at } }, null, 2)}\n`);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
process.stdout.write(`Opening browser approval: ${registered.claim_url}\n`);
|
|
33
|
+
}
|
|
34
|
+
if (options.open !== false) {
|
|
35
|
+
openInBrowser(registered.claim_url);
|
|
36
|
+
}
|
|
37
|
+
const claimed = await waitForClaim(apiUrl, registered.claim_token, timeoutSeconds);
|
|
38
|
+
if (!claimed.api_key) {
|
|
39
|
+
throw new Error("Browser approval completed, but the API did not return a CLI token.");
|
|
40
|
+
}
|
|
41
|
+
writeStoredAuth({
|
|
42
|
+
apiUrl,
|
|
43
|
+
apiKey: claimed.api_key,
|
|
44
|
+
orgId: claimed.org_id ?? undefined,
|
|
45
|
+
userEmail: claimed.user_email ?? undefined,
|
|
46
|
+
userId: claimed.user_id ?? undefined,
|
|
47
|
+
apiKeyId: claimed.api_key_id ?? undefined,
|
|
48
|
+
savedAt: new Date().toISOString(),
|
|
49
|
+
});
|
|
50
|
+
printResult({
|
|
51
|
+
apiUrl,
|
|
52
|
+
apiKey: claimed.api_key,
|
|
53
|
+
orgId: claimed.org_id ?? undefined,
|
|
54
|
+
json: isJsonMode(loginCommand),
|
|
55
|
+
}, {
|
|
56
|
+
authenticated: true,
|
|
57
|
+
api_url: apiUrl,
|
|
58
|
+
org_id: claimed.org_id,
|
|
59
|
+
org_name: claimed.org_name,
|
|
60
|
+
user_email: claimed.user_email,
|
|
61
|
+
config_path: authConfigPath(),
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
const statusCommand = auth.command("status").description("Show the saved CLI auth state");
|
|
65
|
+
statusCommand.action(async () => {
|
|
66
|
+
const apiUrl = resolveApiUrl(statusCommand);
|
|
67
|
+
const stored = readStoredAuth();
|
|
68
|
+
const storedMatchesApiUrl = stored?.apiUrl.replace(/\/+$/, "") === apiUrl;
|
|
69
|
+
if (!stored || !storedMatchesApiUrl) {
|
|
70
|
+
printAuthResult(statusCommand, {
|
|
71
|
+
authenticated: false,
|
|
72
|
+
api_url: apiUrl,
|
|
73
|
+
config_path: authConfigPath(),
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const orgs = await apiRequest(apiUrl, "/v1/auth/orgs", {
|
|
78
|
+
method: "GET",
|
|
79
|
+
apiKey: stored.apiKey,
|
|
80
|
+
orgId: stored.orgId,
|
|
81
|
+
});
|
|
82
|
+
printAuthResult(statusCommand, {
|
|
83
|
+
authenticated: true,
|
|
84
|
+
api_url: apiUrl,
|
|
85
|
+
org_id: stored.orgId,
|
|
86
|
+
user_email: stored.userEmail,
|
|
87
|
+
orgs: orgs.orgs,
|
|
88
|
+
config_path: authConfigPath(),
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
const logoutCommand = auth.command("logout").description("Remove the saved CLI token from this machine");
|
|
92
|
+
logoutCommand.action(async () => {
|
|
93
|
+
const removed = clearStoredAuth();
|
|
94
|
+
printAuthResult(logoutCommand, {
|
|
95
|
+
authenticated: false,
|
|
96
|
+
removed,
|
|
97
|
+
config_path: authConfigPath(),
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async function waitForClaim(apiUrl, claimToken, timeoutSeconds) {
|
|
102
|
+
const deadline = Date.now() + timeoutSeconds * 1000;
|
|
103
|
+
while (Date.now() <= deadline) {
|
|
104
|
+
const status = await apiRequest(apiUrl, "/v1/auth/cli/status", {
|
|
105
|
+
method: "POST",
|
|
106
|
+
body: {
|
|
107
|
+
claim_token: claimToken,
|
|
108
|
+
reveal: true,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
if (status.status === "claimed")
|
|
112
|
+
return status;
|
|
113
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
114
|
+
}
|
|
115
|
+
throw new Error("Still waiting for browser approval. Re-run `ethos auth login` when you are ready to try again.");
|
|
116
|
+
}
|
|
117
|
+
async function apiRequest(apiUrl, path, options = { method: "GET" }) {
|
|
118
|
+
const headers = new Headers();
|
|
119
|
+
if (options.body !== undefined)
|
|
120
|
+
headers.set("Content-Type", "application/json");
|
|
121
|
+
if (options.apiKey)
|
|
122
|
+
headers.set("Authorization", `Bearer ${options.apiKey}`);
|
|
123
|
+
if (options.orgId)
|
|
124
|
+
headers.set("X-Org-Id", options.orgId);
|
|
125
|
+
const response = await fetch(`${apiUrl}${path}`, {
|
|
126
|
+
method: options.method,
|
|
127
|
+
headers,
|
|
128
|
+
body: options.body === undefined ? undefined : JSON.stringify(options.body),
|
|
129
|
+
});
|
|
130
|
+
const envelope = (await response.json());
|
|
131
|
+
if (!response.ok || envelope.success === false) {
|
|
132
|
+
throw new Error(getErrorMessage(envelope.error ?? envelope.detail ?? envelope, response.status));
|
|
133
|
+
}
|
|
134
|
+
return envelope.response;
|
|
135
|
+
}
|
|
136
|
+
function parseTimeout(value) {
|
|
137
|
+
const parsed = Number.parseInt(value || "", 10);
|
|
138
|
+
if (!Number.isFinite(parsed) || parsed < 1)
|
|
139
|
+
throw new Error("--timeout must be a positive number of seconds.");
|
|
140
|
+
return Math.min(parsed, 600);
|
|
141
|
+
}
|
|
142
|
+
function inferAppUrl(apiUrl) {
|
|
143
|
+
try {
|
|
144
|
+
const url = new URL(apiUrl);
|
|
145
|
+
if (url.hostname === "localhost" || url.hostname === "127.0.0.1") {
|
|
146
|
+
url.port = url.port === "8001" ? "3001" : "3000";
|
|
147
|
+
return url.toString().replace(/\/+$/, "");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// Fall through to production default.
|
|
152
|
+
}
|
|
153
|
+
return "https://ethos.hello-cluster.com";
|
|
154
|
+
}
|
|
155
|
+
function openInBrowser(url) {
|
|
156
|
+
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
157
|
+
const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
158
|
+
try {
|
|
159
|
+
const child = spawn(command, args, { detached: true, stdio: "ignore" });
|
|
160
|
+
child.unref();
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// The approval URL was already printed.
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function printAuthResult(command, response) {
|
|
167
|
+
const apiUrl = resolveApiUrl(command);
|
|
168
|
+
printResult({ apiUrl, apiKey: "", json: isJsonMode(command) }, response);
|
|
169
|
+
}
|
|
170
|
+
function getErrorMessage(error, status) {
|
|
171
|
+
if (typeof error === "string")
|
|
172
|
+
return error;
|
|
173
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
174
|
+
const message = error.message;
|
|
175
|
+
if (typeof message === "string")
|
|
176
|
+
return message;
|
|
177
|
+
}
|
|
178
|
+
return `API request failed: ${status}`;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { isJsonMode } from "../lib/config.js";
|
|
5
|
+
import { printResult } from "../lib/output.js";
|
|
6
|
+
import { AGENTS, readLockfile, removeAllSkills, syncSkills, } from "../skills-installer/index.js";
|
|
7
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const SKILLS_DIR = join(here, "..", "..", "skills");
|
|
9
|
+
const pkg = createRequire(import.meta.url)("../../package.json");
|
|
10
|
+
const ALL_AGENTS = Object.keys(AGENTS);
|
|
11
|
+
export function registerSkills(program) {
|
|
12
|
+
const skills = program
|
|
13
|
+
.command("skills")
|
|
14
|
+
.description("Install bundled Ethos skills into supported coding agents. This normally runs during npm install.");
|
|
15
|
+
const installCommand = skills
|
|
16
|
+
.command("install")
|
|
17
|
+
.description("Install bundled Ethos skills into detected agents")
|
|
18
|
+
.option("-a, --agents <list>", `comma-separated agents (default: auto-detect). Supported: ${ALL_AGENTS.join(", ")}`);
|
|
19
|
+
installCommand.action(async () => {
|
|
20
|
+
const result = await syncSkills({
|
|
21
|
+
bundledSkillsDir: SKILLS_DIR,
|
|
22
|
+
ethosVersion: pkg.version,
|
|
23
|
+
agents: parseAgentList(installCommand.opts().agents),
|
|
24
|
+
});
|
|
25
|
+
printSkillsResult(installCommand, {
|
|
26
|
+
label: `Targets: ${result.targetAgents.map((agent) => AGENTS[agent].displayName).join(", ") ||
|
|
27
|
+
"(none detected - pass --agents to force)"}`,
|
|
28
|
+
data: {
|
|
29
|
+
target_agents: result.targetAgents,
|
|
30
|
+
skipped_agents: result.skippedAgents,
|
|
31
|
+
installed: result.installed,
|
|
32
|
+
updated: result.updated,
|
|
33
|
+
removed: result.removed,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
const listCommand = skills
|
|
38
|
+
.command("list")
|
|
39
|
+
.description("Show Ethos-installed skills and where they live on disk");
|
|
40
|
+
listCommand.action(async () => {
|
|
41
|
+
const lock = await readLockfile();
|
|
42
|
+
const installedSkills = Object.entries(lock.skills).map(([name, entry]) => ({
|
|
43
|
+
name,
|
|
44
|
+
installed_at: entry.installedAt,
|
|
45
|
+
agents: Object.fromEntries(Object.entries(entry.agents).map(([agent, info]) => [agent, info?.path])),
|
|
46
|
+
}));
|
|
47
|
+
printSkillsResult(listCommand, {
|
|
48
|
+
label: installedSkills.length
|
|
49
|
+
? `Installed Ethos skills: ${installedSkills.map((skill) => skill.name).join(", ")}`
|
|
50
|
+
: "No Ethos skills installed. Run `ethos skills install`.",
|
|
51
|
+
data: {
|
|
52
|
+
ethos_version: lock.ethosVersion,
|
|
53
|
+
count: installedSkills.length,
|
|
54
|
+
skills: installedSkills,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
const removeCommand = skills
|
|
59
|
+
.command("remove")
|
|
60
|
+
.description("Remove every Ethos-installed skill from every agent");
|
|
61
|
+
removeCommand.action(async () => {
|
|
62
|
+
const removed = await removeAllSkills();
|
|
63
|
+
printSkillsResult(removeCommand, {
|
|
64
|
+
label: removed.length ? `Removed: ${removed.join(", ")}` : "Nothing to remove.",
|
|
65
|
+
data: { removed },
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function parseAgentList(value) {
|
|
70
|
+
if (!value)
|
|
71
|
+
return undefined;
|
|
72
|
+
const agents = value
|
|
73
|
+
.split(",")
|
|
74
|
+
.map((part) => part.trim())
|
|
75
|
+
.filter(Boolean);
|
|
76
|
+
const parsed = [];
|
|
77
|
+
for (const agent of agents) {
|
|
78
|
+
if (ALL_AGENTS.includes(agent)) {
|
|
79
|
+
parsed.push(agent);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
throw new Error(`unknown agent: ${agent} (supported: ${ALL_AGENTS.join(", ")})`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return parsed;
|
|
86
|
+
}
|
|
87
|
+
function printSkillsResult(command, result) {
|
|
88
|
+
printResult({ apiUrl: "", apiKey: "", json: isJsonMode(command) }, result);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/commands/skills.ts"],"names":[],"mappings":"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"}
|