@enter-pro/enter-cli 0.4.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.
Files changed (51) hide show
  1. package/README.md +0 -0
  2. package/dist/auth.d.ts +12 -0
  3. package/dist/auth.js +39 -0
  4. package/dist/auth.js.map +1 -0
  5. package/dist/client.d.ts +11 -0
  6. package/dist/client.js +140 -0
  7. package/dist/client.js.map +1 -0
  8. package/dist/commands/config.d.ts +2 -0
  9. package/dist/commands/config.js +37 -0
  10. package/dist/commands/config.js.map +1 -0
  11. package/dist/commands/domain.d.ts +2 -0
  12. package/dist/commands/domain.js +65 -0
  13. package/dist/commands/domain.js.map +1 -0
  14. package/dist/commands/login.d.ts +2 -0
  15. package/dist/commands/login.js +143 -0
  16. package/dist/commands/login.js.map +1 -0
  17. package/dist/commands/logout.d.ts +2 -0
  18. package/dist/commands/logout.js +9 -0
  19. package/dist/commands/logout.js.map +1 -0
  20. package/dist/commands/models.d.ts +2 -0
  21. package/dist/commands/models.js +27 -0
  22. package/dist/commands/project.d.ts +2 -0
  23. package/dist/commands/project.js +452 -0
  24. package/dist/commands/project.js.map +1 -0
  25. package/dist/commands/skill.d.ts +2 -0
  26. package/dist/commands/skill.js +118 -0
  27. package/dist/commands/thread.d.ts +2 -0
  28. package/dist/commands/thread.js +578 -0
  29. package/dist/commands/thread.js.map +1 -0
  30. package/dist/commands/whoami.d.ts +2 -0
  31. package/dist/commands/whoami.js +28 -0
  32. package/dist/commands/whoami.js.map +1 -0
  33. package/dist/commands/workspace.d.ts +2 -0
  34. package/dist/commands/workspace.js +178 -0
  35. package/dist/commands/workspace.js.map +1 -0
  36. package/dist/config.d.ts +13 -0
  37. package/dist/config.js +68 -0
  38. package/dist/config.js.map +1 -0
  39. package/dist/errors.d.ts +13 -0
  40. package/dist/errors.js +33 -0
  41. package/dist/index.d.ts +2 -0
  42. package/dist/index.js +45 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/lifecycle.d.ts +9 -0
  45. package/dist/lifecycle.js +47 -0
  46. package/dist/output.d.ts +26 -0
  47. package/dist/output.js +89 -0
  48. package/dist/output.js.map +1 -0
  49. package/dist/poll.d.ts +9 -0
  50. package/dist/poll.js +24 -0
  51. package/package.json +41 -0
package/README.md ADDED
File without changes
package/dist/auth.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export interface Credentials {
2
+ access_token: string;
3
+ refresh_token?: string;
4
+ id_token?: string;
5
+ token_type: string;
6
+ expires_at?: string;
7
+ }
8
+ export declare function saveCredentials(creds: Credentials): void;
9
+ export declare function loadCredentials(): Credentials | null;
10
+ export declare function clearCredentials(): void;
11
+ export declare function getToken(): string;
12
+ export declare function isAuthenticated(): boolean;
package/dist/auth.js ADDED
@@ -0,0 +1,39 @@
1
+ import { readFileSync, writeFileSync, unlinkSync } from "fs";
2
+ import { join } from "path";
3
+ import { configDir } from "./config.js";
4
+ const CREDENTIALS_FILE = "credentials.json";
5
+ function credentialsPath() {
6
+ return join(configDir(), CREDENTIALS_FILE);
7
+ }
8
+ export function saveCredentials(creds) {
9
+ writeFileSync(credentialsPath(), JSON.stringify(creds, null, 2), {
10
+ mode: 0o600,
11
+ });
12
+ }
13
+ export function loadCredentials() {
14
+ try {
15
+ const data = readFileSync(credentialsPath(), "utf-8");
16
+ return JSON.parse(data);
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ export function clearCredentials() {
23
+ try {
24
+ unlinkSync(credentialsPath());
25
+ }
26
+ catch {
27
+ // ignore if file doesn't exist
28
+ }
29
+ }
30
+ export function getToken() {
31
+ const apiKey = process.env.ENTER_API_KEY;
32
+ if (apiKey)
33
+ return apiKey;
34
+ const creds = loadCredentials();
35
+ return creds?.access_token || "";
36
+ }
37
+ export function isAuthenticated() {
38
+ return getToken() !== "";
39
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AAU5C,SAAS,eAAe;IACtB,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,aAAa,CAAC,eAAe,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QAC/D,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,CAAC,eAAe,EAAE,EAAE,OAAO,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC;QACH,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,OAAO,KAAK,EAAE,YAAY,IAAI,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare function setVerbose(v: boolean): void;
2
+ export declare function get(path: string, params?: Record<string, string>): Promise<unknown>;
3
+ export declare function post(path: string, body?: unknown): Promise<unknown>;
4
+ export declare function del(path: string): Promise<unknown>;
5
+ export declare function put(path: string, body?: unknown): Promise<unknown>;
6
+ export declare function patch(path: string, body?: unknown): Promise<unknown>;
7
+ export declare function workGet(path: string, params?: Record<string, string>): Promise<unknown>;
8
+ export declare function workPost(path: string, body?: unknown): Promise<unknown>;
9
+ export declare function workPatch(path: string, body?: unknown): Promise<unknown>;
10
+ export declare function workDel(path: string): Promise<unknown>;
11
+ export declare function getRaw(path: string): Promise<Response>;
package/dist/client.js ADDED
@@ -0,0 +1,140 @@
1
+ import { baseURL, workURL } from "./config.js";
2
+ import { getToken } from "./auth.js";
3
+ import { APIError } from "./errors.js";
4
+ const CODE_SUCCESS = 0;
5
+ let verbose = false;
6
+ export function setVerbose(v) {
7
+ verbose = v;
8
+ }
9
+ async function request(method, path, options, base) {
10
+ let url = `${base ?? baseURL()}${path}`;
11
+ if (options?.params) {
12
+ const qs = new URLSearchParams(options.params).toString();
13
+ if (qs)
14
+ url += `?${qs}`;
15
+ }
16
+ const headers = {
17
+ "Content-Type": "application/json",
18
+ };
19
+ const token = getToken();
20
+ if (token)
21
+ headers["Authorization"] = `Bearer ${token}`;
22
+ const init = { method, headers };
23
+ if (options?.body !== undefined) {
24
+ init.body = JSON.stringify(options.body);
25
+ }
26
+ if (verbose) {
27
+ console.error(`> ${method} ${url}`);
28
+ if (options?.body)
29
+ console.error(`> Body: ${JSON.stringify(options.body)}`);
30
+ }
31
+ const resp = await fetch(url, init);
32
+ if (verbose) {
33
+ console.error(`< ${resp.status} ${resp.statusText}`);
34
+ }
35
+ if (resp.status === 401) {
36
+ throw new Error("Authentication required. Run `enter login` or set ENTER_API_KEY environment variable.");
37
+ }
38
+ const text = await resp.text();
39
+ let apiResp;
40
+ try {
41
+ apiResp = JSON.parse(text);
42
+ }
43
+ catch {
44
+ if (resp.status >= 400) {
45
+ throw new Error(`HTTP ${resp.status}: ${text}`);
46
+ }
47
+ return JSON.parse(text);
48
+ }
49
+ if (apiResp.code === undefined) {
50
+ // Endpoint returns raw JSON without the standard {code,message,data} envelope.
51
+ // Surface the parsed body as-is.
52
+ if (resp.status >= 400) {
53
+ throw new Error(`HTTP ${resp.status}: ${text}`);
54
+ }
55
+ return apiResp;
56
+ }
57
+ if (apiResp.code !== CODE_SUCCESS) {
58
+ throw new APIError(apiResp.code, apiResp.message ?? "", apiResp.detail ?? "");
59
+ }
60
+ return apiResp.data;
61
+ }
62
+ export async function get(path, params) {
63
+ return request("GET", path, { params });
64
+ }
65
+ export async function post(path, body) {
66
+ return request("POST", path, { body });
67
+ }
68
+ export async function del(path) {
69
+ return request("DELETE", path);
70
+ }
71
+ export async function put(path, body) {
72
+ return request("PUT", path, { body });
73
+ }
74
+ export async function patch(path, body) {
75
+ return request("PATCH", path, { body });
76
+ }
77
+ // work API helpers (base: /work/api)
78
+ export async function workGet(path, params) {
79
+ return request("GET", path, { params }, workURL());
80
+ }
81
+ export async function workPost(path, body) {
82
+ return request("POST", path, { body }, workURL());
83
+ }
84
+ export async function workPatch(path, body) {
85
+ return request("PATCH", path, { body }, workURL());
86
+ }
87
+ export async function workDel(path) {
88
+ return request("DELETE", path, {}, workURL());
89
+ }
90
+ export async function getRaw(path) {
91
+ const url = `${baseURL()}${path}`;
92
+ const headers = {};
93
+ const token = getToken();
94
+ if (token)
95
+ headers["Authorization"] = `Bearer ${token}`;
96
+ if (verbose)
97
+ console.error(`> GET ${url}`);
98
+ const resp = await fetch(url, { headers });
99
+ if (verbose)
100
+ console.error(`< ${resp.status} ${resp.statusText}`);
101
+ if (resp.status === 401) {
102
+ throw new Error("Authentication required. Run `enter login` or set ENTER_API_KEY environment variable.");
103
+ }
104
+ // Successful binary response — caller consumes the body.
105
+ if (resp.ok) {
106
+ // But: a JSON error envelope can come back with status 200 too. Peek the
107
+ // content-type; only treat as raw if it's not JSON.
108
+ const ct = resp.headers.get("content-type") ?? "";
109
+ if (!ct.includes("application/json"))
110
+ return resp;
111
+ const text = await resp.text();
112
+ try {
113
+ const apiResp = JSON.parse(text);
114
+ if (apiResp.code !== 0) {
115
+ throw new APIError(apiResp.code, apiResp.message, apiResp.detail);
116
+ }
117
+ // code === 0 with JSON body on a binary endpoint shouldn't happen; surface as raw text
118
+ throw new Error(`Unexpected JSON response on binary endpoint: ${text.slice(0, 200)}`);
119
+ }
120
+ catch (err) {
121
+ if (err instanceof APIError)
122
+ throw err;
123
+ throw new Error(`Failed to parse JSON response: ${text.slice(0, 200)}`);
124
+ }
125
+ }
126
+ // Non-2xx — try to parse the API error envelope so callers can distinguish
127
+ // VIP_REQUIRED, NOT_FOUND, etc. Fall back to raw text if it isn't JSON.
128
+ const text = await resp.text();
129
+ try {
130
+ const apiResp = JSON.parse(text);
131
+ if (apiResp.code !== undefined) {
132
+ throw new APIError(apiResp.code, apiResp.message ?? "", apiResp.detail ?? "");
133
+ }
134
+ }
135
+ catch (err) {
136
+ if (err instanceof APIError)
137
+ throw err;
138
+ }
139
+ throw new Error(`HTTP ${resp.status}: ${text || resp.statusText}`);
140
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const configCmd: Command;
@@ -0,0 +1,37 @@
1
+ import { Command } from "commander";
2
+ import { setConfig, getConfig, allSettings } from "../config.js";
3
+ import { print, printMessage, printTable } from "../output.js";
4
+ export const configCmd = new Command("config").description("Manage CLI configuration");
5
+ configCmd
6
+ .command("set <key> <value>")
7
+ .description("Set a configuration value")
8
+ .action(async (key, value) => {
9
+ setConfig(key, value);
10
+ printMessage(`Set ${key} = ${value}`);
11
+ });
12
+ configCmd
13
+ .command("get <key>")
14
+ .description("Get a configuration value")
15
+ .action(async (key) => {
16
+ const val = getConfig(key);
17
+ if (!val) {
18
+ printMessage(`${key}: (not set)`);
19
+ }
20
+ else {
21
+ printMessage(`${key}: ${val}`);
22
+ }
23
+ });
24
+ configCmd
25
+ .command("list")
26
+ .description("List all configuration values")
27
+ .action(async (_opts, cmd) => {
28
+ const settings = allSettings();
29
+ const format = cmd.optsWithGlobals().output || "json";
30
+ if (format !== "table") {
31
+ print(format, settings);
32
+ return;
33
+ }
34
+ const keys = Object.keys(settings).sort();
35
+ const rows = keys.map((k) => [k, String(settings[k] ?? "")]);
36
+ printTable(["Key", "Value"], rows);
37
+ });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/D,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CACxD,0BAA0B,CAC3B,CAAC;AAEF,SAAS;KACN,OAAO,CAAC,mBAAmB,CAAC;KAC5B,WAAW,CAAC,2BAA2B,CAAC;KACxC,MAAM,CAAC,KAAK,EAAE,GAAW,EAAE,KAAa,EAAE,EAAE;IAC3C,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACtB,YAAY,CAAC,OAAO,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC;AACxC,CAAC,CAAC,CAAC;AAEL,SAAS;KACN,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CAAC,2BAA2B,CAAC;KACxC,MAAM,CAAC,KAAK,EAAE,GAAW,EAAE,EAAE;IAC5B,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,YAAY,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,GAAG,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,SAAS;KACN,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,+BAA+B,CAAC;KAC5C,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IAC3B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC,MAAM,IAAI,MAAM,CAAC;IACtD,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACxB,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7D,UAAU,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const domainCmd: Command;
@@ -0,0 +1,65 @@
1
+ import { Command } from "commander";
2
+ import * as client from "../client.js";
3
+ import { print, printMessage, printTable } from "../output.js";
4
+ export const domainCmd = new Command("domain").description("Manage project domains");
5
+ function getFormat(cmd) {
6
+ return cmd.optsWithGlobals().output || "json";
7
+ }
8
+ domainCmd
9
+ .command("list <project_id>")
10
+ .description("List project domains")
11
+ .action(async (id, _opts, cmd) => {
12
+ const data = await client.get(`/v1/projects/${id}/domains`);
13
+ const format = getFormat(cmd);
14
+ if (format !== "table") {
15
+ print(format, data);
16
+ return;
17
+ }
18
+ const resp = data;
19
+ const rows = (resp.domains || []).map((d) => [
20
+ d.domain,
21
+ d.status,
22
+ d.created_at,
23
+ ]);
24
+ printTable(["Domain", "Status", "Created"], rows);
25
+ });
26
+ domainCmd
27
+ .command("add <project_id>")
28
+ .description("Add a custom domain to project")
29
+ .requiredOption("--domain <name>", "Domain name")
30
+ .action(async (id, opts, cmd) => {
31
+ const data = await client.post(`/v1/projects/${id}/domain`, {
32
+ domain: opts.domain,
33
+ });
34
+ print(getFormat(cmd), data);
35
+ });
36
+ domainCmd
37
+ .command("remove <project_id>")
38
+ .description("Remove a custom domain from project")
39
+ .requiredOption("--domain <name>", "Domain name to remove")
40
+ .action(async (id, opts) => {
41
+ await client.del(`/v1/projects/${id}/domain?domain=${opts.domain}`);
42
+ printMessage(`Domain "${opts.domain}" removed.`);
43
+ });
44
+ domainCmd
45
+ .command("refresh <project_id>")
46
+ .description("Refresh a custom domain (re-check DNS and SSL)")
47
+ .requiredOption("--domain <name>", "Domain name to refresh")
48
+ .action(async (id, opts, cmd) => {
49
+ const data = await client.post(`/v1/projects/${id}/domain/refresh`, {
50
+ domain: opts.domain,
51
+ });
52
+ print(getFormat(cmd), data);
53
+ });
54
+ domainCmd
55
+ .command("update <project_id>")
56
+ .description("Update a custom domain configuration")
57
+ .requiredOption("--domain <name>", "Domain name to update")
58
+ .option("--new-domain <name>", "New domain name")
59
+ .action(async (id, opts, cmd) => {
60
+ const body = { domain: opts.domain };
61
+ if (opts.newDomain)
62
+ body.new_domain = opts.newDomain;
63
+ const data = await client.post(`/v1/projects/${id}/domain/update`, body);
64
+ print(getFormat(cmd), data);
65
+ });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain.js","sourceRoot":"","sources":["../../src/commands/domain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/D,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CACxD,wBAAwB,CACzB,CAAC;AAEF,SAAS,SAAS,CAAC,GAAY;IAC7B,OAAO,GAAG,CAAC,eAAe,EAAE,CAAC,MAAM,IAAI,MAAM,CAAC;AAChD,CAAC;AAED,SAAS;KACN,OAAO,CAAC,mBAAmB,CAAC;KAC5B,WAAW,CAAC,sBAAsB,CAAC;KACnC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IACvC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,IAMZ,CAAC;IAEF,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC3C,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,UAAU;KACb,CAAC,CAAC;IACH,UAAU,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEL,SAAS;KACN,OAAO,CAAC,kBAAkB,CAAC;KAC3B,WAAW,CAAC,gCAAgC,CAAC;KAC7C,cAAc,CAAC,iBAAiB,EAAE,aAAa,CAAC;KAChD,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;IACtC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,SAAS,EAAE;QAC1D,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;IACH,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AAC9B,CAAC,CAAC,CAAC;AAEL,SAAS;KACN,OAAO,CAAC,qBAAqB,CAAC;KAC9B,WAAW,CAAC,qCAAqC,CAAC;KAClD,cAAc,CAAC,iBAAiB,EAAE,uBAAuB,CAAC;KAC1D,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAI,EAAE,EAAE;IACjC,MAAM,MAAM,CAAC,GAAG,CACd,gBAAgB,EAAE,kBAAkB,IAAI,CAAC,MAAM,EAAE,CAClD,CAAC;IACF,YAAY,CAAC,WAAW,IAAI,CAAC,MAAM,YAAY,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const loginCmd: Command;
@@ -0,0 +1,143 @@
1
+ import { Command } from "commander";
2
+ import { createServer } from "http";
3
+ import { randomBytes, createHash } from "crypto";
4
+ import { execSync } from "child_process";
5
+ import { saveCredentials } from "../auth.js";
6
+ import { printMessage } from "../output.js";
7
+ const AUTH0_DOMAIN = "auth.enter.pro";
8
+ const CLIENT_ID = "TZvnfnosSwQh9UmOTxmcWiIJ7CqFrsln";
9
+ const AUTHORIZE_URL = `https://${AUTH0_DOMAIN}/authorize`;
10
+ const TOKEN_URL = `https://${AUTH0_DOMAIN}/oauth/token`;
11
+ const AUDIENCE = "https://api.enter.pro";
12
+ const SCOPE = "openid profile email offline_access";
13
+ const REDIRECT_URI = "http://localhost:19820";
14
+ const PORT = 19820;
15
+ function generateCodeVerifier() {
16
+ return randomBytes(32).toString("base64url");
17
+ }
18
+ function generateCodeChallenge(verifier) {
19
+ return createHash("sha256").update(verifier).digest("base64url");
20
+ }
21
+ function openBrowser(url) {
22
+ const platform = process.platform;
23
+ const cmd = platform === "darwin"
24
+ ? "open"
25
+ : platform === "win32"
26
+ ? "start"
27
+ : "xdg-open";
28
+ try {
29
+ execSync(`${cmd} "${url}"`);
30
+ }
31
+ catch {
32
+ // Browser open failed, user can manually copy the URL
33
+ }
34
+ }
35
+ async function exchangeCodeForTokens(code, codeVerifier) {
36
+ const res = await fetch(TOKEN_URL, {
37
+ method: "POST",
38
+ headers: { "Content-Type": "application/json" },
39
+ body: JSON.stringify({
40
+ grant_type: "authorization_code",
41
+ client_id: CLIENT_ID,
42
+ code,
43
+ code_verifier: codeVerifier,
44
+ redirect_uri: REDIRECT_URI,
45
+ }),
46
+ });
47
+ if (!res.ok) {
48
+ const text = await res.text();
49
+ throw new Error(`Token exchange failed (${res.status}): ${text}`);
50
+ }
51
+ return res.json();
52
+ }
53
+ function startOAuthFlow() {
54
+ return new Promise((resolve, reject) => {
55
+ const codeVerifier = generateCodeVerifier();
56
+ const codeChallenge = generateCodeChallenge(codeVerifier);
57
+ let timeoutId;
58
+ const server = createServer(async (req, res) => {
59
+ const url = new URL(req.url, `http://localhost`);
60
+ if (url.pathname !== "/") {
61
+ res.writeHead(404);
62
+ res.end();
63
+ return;
64
+ }
65
+ const code = url.searchParams.get("code");
66
+ const error = url.searchParams.get("error");
67
+ const errorDescription = url.searchParams.get("error_description");
68
+ if (error) {
69
+ res.writeHead(200, { "Content-Type": "text/html" });
70
+ res.end(`<html><body><h2>Login Failed</h2><p>${errorDescription || error}</p><p>You can close this window.</p></body></html>`);
71
+ clearTimeout(timeoutId);
72
+ server.close();
73
+ reject(new Error(errorDescription || error));
74
+ return;
75
+ }
76
+ if (!code) {
77
+ res.writeHead(400, { "Content-Type": "text/html" });
78
+ res.end(`<html><body><h2>Error</h2><p>No authorization code received.</p></body></html>`);
79
+ clearTimeout(timeoutId);
80
+ server.close();
81
+ reject(new Error("No authorization code received"));
82
+ return;
83
+ }
84
+ try {
85
+ const tokens = await exchangeCodeForTokens(code, codeVerifier);
86
+ const expiresAt = new Date(Date.now() + tokens.expires_in * 1000).toISOString();
87
+ saveCredentials({
88
+ access_token: tokens.access_token,
89
+ refresh_token: tokens.refresh_token,
90
+ id_token: tokens.id_token,
91
+ token_type: tokens.token_type || "Bearer",
92
+ expires_at: expiresAt,
93
+ });
94
+ res.writeHead(200, { "Content-Type": "text/html" });
95
+ res.end(`<html><body><h2>Login Successful!</h2><p>You can close this window and return to the terminal.</p></body></html>`);
96
+ printMessage("Login successful. Credentials saved.");
97
+ clearTimeout(timeoutId);
98
+ server.close();
99
+ resolve();
100
+ }
101
+ catch (err) {
102
+ res.writeHead(500, { "Content-Type": "text/html" });
103
+ res.end(`<html><body><h2>Error</h2><p>${err.message}</p></body></html>`);
104
+ clearTimeout(timeoutId);
105
+ server.close();
106
+ reject(err);
107
+ }
108
+ });
109
+ server.listen(PORT, "127.0.0.1", () => {
110
+ const params = new URLSearchParams({
111
+ response_type: "code",
112
+ client_id: CLIENT_ID,
113
+ redirect_uri: REDIRECT_URI,
114
+ audience: AUDIENCE,
115
+ scope: SCOPE,
116
+ code_challenge: codeChallenge,
117
+ code_challenge_method: "S256",
118
+ });
119
+ const authUrl = `${AUTHORIZE_URL}?${params}`;
120
+ printMessage("Opening browser for authentication...");
121
+ printMessage(`If browser doesn't open, visit:\n${authUrl}\n`);
122
+ openBrowser(authUrl);
123
+ });
124
+ timeoutId = setTimeout(() => {
125
+ server.close();
126
+ reject(new Error("Login timed out after 5 minutes"));
127
+ }, 5 * 60 * 1000);
128
+ });
129
+ }
130
+ export const loginCmd = new Command("login")
131
+ .description("Authenticate with Enter platform")
132
+ .option("--api-key <key>", "Authenticate with a workspace API key instead of OAuth")
133
+ .action(async (opts) => {
134
+ if (opts.apiKey) {
135
+ saveCredentials({
136
+ access_token: opts.apiKey,
137
+ token_type: "Bearer",
138
+ });
139
+ printMessage("API key saved. You are now authenticated.");
140
+ return;
141
+ }
142
+ await startOAuthFlow();
143
+ });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const logoutCmd: Command;
@@ -0,0 +1,9 @@
1
+ import { Command } from "commander";
2
+ import { clearCredentials } from "../auth.js";
3
+ import { printMessage } from "../output.js";
4
+ export const logoutCmd = new Command("logout")
5
+ .description("Clear stored credentials")
6
+ .action(async () => {
7
+ clearCredentials();
8
+ printMessage("Logged out successfully.");
9
+ });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC3C,WAAW,CAAC,0BAA0B,CAAC;KACvC,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,gBAAgB,EAAE,CAAC;IACnB,YAAY,CAAC,0BAA0B,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const modelsCmd: Command;
@@ -0,0 +1,27 @@
1
+ import { Command } from "commander";
2
+ import * as client from "../client.js";
3
+ import { print, printTable } from "../output.js";
4
+ export const modelsCmd = new Command("models")
5
+ .description("Browse available AI models");
6
+ modelsCmd
7
+ .command("list")
8
+ .description("List AI models supported by Enter agent (catalog backing `proj create --model`)")
9
+ .action(async (_opts, cmd) => {
10
+ // GET /v1/models is a public endpoint — no auth required.
11
+ const data = await client.get("/v1/models");
12
+ const models = (data?.models ?? []);
13
+ const format = cmd.optsWithGlobals().output || "json";
14
+ if (format !== "table") {
15
+ print(format, models);
16
+ return;
17
+ }
18
+ printTable(["ID", "Name", "Speed", "Intelligence", "Cost", "Default", "Newest"], models.map((m) => [
19
+ String(m.id ?? ""),
20
+ String(m.name ?? ""),
21
+ m.speed != null ? String(m.speed) : "-",
22
+ m.intelligence != null ? String(m.intelligence) : "-",
23
+ String(m.cost ?? "-"),
24
+ m.is_default ? "yes" : "",
25
+ m.is_newest ? "yes" : "",
26
+ ]));
27
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare const projectCmd: Command;