@eightstate/escli 0.5.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/CONVENTIONS.md +59 -0
- package/LICENSE +21 -0
- package/README.md +106 -0
- package/RELEASE-NOTES-0.5.0.md +34 -0
- package/dist/base-command.js +166 -0
- package/dist/commands/audio/get.js +39 -0
- package/dist/commands/audio/index.js +18 -0
- package/dist/commands/audio/list.js +39 -0
- package/dist/commands/audio/status.js +34 -0
- package/dist/commands/audio/transcribe.js +99 -0
- package/dist/commands/auth/index.js +18 -0
- package/dist/commands/auth/login.js +38 -0
- package/dist/commands/auth/logout.js +27 -0
- package/dist/commands/auth/profiles.js +31 -0
- package/dist/commands/auth/status.js +27 -0
- package/dist/commands/auth/switch.js +24 -0
- package/dist/commands/docs/fetch.js +37 -0
- package/dist/commands/docs/get.js +47 -0
- package/dist/commands/docs/index.js +18 -0
- package/dist/commands/docs/search.js +55 -0
- package/dist/commands/fetch.js +55 -0
- package/dist/commands/image/edit.js +59 -0
- package/dist/commands/image/generate.js +67 -0
- package/dist/commands/image/index.js +18 -0
- package/dist/commands/models.js +27 -0
- package/dist/commands/research.js +92 -0
- package/dist/commands/search.js +54 -0
- package/dist/commands/social.js +69 -0
- package/dist/commands/usage.js +51 -0
- package/dist/commands/version.js +22 -0
- package/dist/entry.js +120 -0
- package/dist/io/io.js +322 -0
- package/dist/lib/build-flags.js +2 -0
- package/dist/lib/command-metadata.js +8 -0
- package/dist/lib/envelope.js +28 -0
- package/dist/lib/escli-error.js +20 -0
- package/dist/lib/global-flags.js +29 -0
- package/dist/lib/globals.js +2 -0
- package/dist/lib/manifest.js +67 -0
- package/dist/lib/oclif-manifest-check.js +11 -0
- package/dist/lib/registry.js +228 -0
- package/dist/services/audio.js +454 -0
- package/dist/services/auth.js +329 -0
- package/dist/services/credentials.js +137 -0
- package/dist/services/docs.js +303 -0
- package/dist/services/fetch.js +197 -0
- package/dist/services/image.js +297 -0
- package/dist/services/models.js +131 -0
- package/dist/services/research.js +504 -0
- package/dist/services/search.js +195 -0
- package/dist/services/social.js +224 -0
- package/dist/services/usage.js +165 -0
- package/oclif.manifest.json +3377 -0
- package/package.json +57 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
4
|
+
import { ExitCodes } from '@eightstate/contracts/exit-codes';
|
|
5
|
+
import { BaseCommand } from '../../base-command.js';
|
|
6
|
+
import { EscliError } from '../../lib/escli-error.js';
|
|
7
|
+
import { authLogin } from '../../services/auth.js';
|
|
8
|
+
export const AuthLoginDataSchema = z.object({
|
|
9
|
+
profile: z.string(),
|
|
10
|
+
auth_type: z.enum(['api_key', 'gate']),
|
|
11
|
+
endpoint: z.string().optional(),
|
|
12
|
+
gate: z.string().optional(),
|
|
13
|
+
key: z.string().optional(),
|
|
14
|
+
models: z.string().optional(),
|
|
15
|
+
config_path: z.string().optional(),
|
|
16
|
+
});
|
|
17
|
+
export default class AuthLogin extends BaseCommand {
|
|
18
|
+
static errors = [ErrorCode.AuthInvalid, ErrorCode.AuthForbidden, ErrorCode.AuthLoginFailed, ErrorCode.AuthSessionExpired, ErrorCode.AuthTimeout, ErrorCode.GateUnavailable, ErrorCode.GateInvalidResponse, ErrorCode.NetworkError, ErrorCode.NetworkTimeout];
|
|
19
|
+
static summary = 'Authenticate via browser or API key';
|
|
20
|
+
static description = 'Authenticate via browser device flow or store an API key profile.';
|
|
21
|
+
static examples = ['<%= config.bin %> auth login', '<%= config.bin %> auth login --key sk-xxx', 'echo sk-xxx | <%= config.bin %> auth login'];
|
|
22
|
+
static aliases = ['auth l'];
|
|
23
|
+
static enableJsonFlag = true;
|
|
24
|
+
static strict = true;
|
|
25
|
+
static flags = {
|
|
26
|
+
key: Flags.string({ char: 'k', description: 'API key for non-interactive login.' }),
|
|
27
|
+
endpoint: Flags.string({ description: 'OpenAI-compatible endpoint for API-key validation.' }),
|
|
28
|
+
profile: Flags.string({ char: 'p', description: 'Profile name.', default: 'default' }),
|
|
29
|
+
label: Flags.string({ description: 'Human label for the profile.' }),
|
|
30
|
+
};
|
|
31
|
+
async execute() {
|
|
32
|
+
const flags = await this.parseFlags(AuthLogin);
|
|
33
|
+
if (flags.key === '')
|
|
34
|
+
throw new EscliError('Missing required flag key', { code: ErrorCode.UsageRequired, exitCode: ExitCodes.Usage });
|
|
35
|
+
return authLogin({ key: flags.key, endpoint: flags.endpoint, profile: flags.profile, label: flags.label, timeoutSeconds: flags.timeout });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import { authLogout } from '../../services/auth.js';
|
|
5
|
+
export const AuthLogoutDataSchema = z.object({
|
|
6
|
+
profile: z.string().optional(),
|
|
7
|
+
deleted: z.boolean().optional(),
|
|
8
|
+
message: z.string().optional(),
|
|
9
|
+
});
|
|
10
|
+
export default class AuthLogout extends BaseCommand {
|
|
11
|
+
static errors = [];
|
|
12
|
+
static summary = 'Remove stored credentials';
|
|
13
|
+
static description = 'Remove one stored auth profile or all profiles.';
|
|
14
|
+
static examples = ['<%= config.bin %> auth logout', '<%= config.bin %> auth logout --profile work', '<%= config.bin %> auth logout --all'];
|
|
15
|
+
static aliases = [];
|
|
16
|
+
static enableJsonFlag = true;
|
|
17
|
+
static strict = true;
|
|
18
|
+
static flags = {
|
|
19
|
+
profile: Flags.string({ char: 'p', description: 'Profile name to remove.' }),
|
|
20
|
+
all: Flags.boolean({ description: 'Remove all profiles.' }),
|
|
21
|
+
};
|
|
22
|
+
async execute() {
|
|
23
|
+
const flags = await this.parseFlags(AuthLogout);
|
|
24
|
+
return authLogout({ profile: flags.profile, all: flags.all });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
import { authProfiles } from '../../services/auth.js';
|
|
4
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
5
|
+
export const AuthProfilesDataSchema = z.object({
|
|
6
|
+
profiles: z.array(z.object({
|
|
7
|
+
name: z.string(),
|
|
8
|
+
label: z.string(),
|
|
9
|
+
key: z.string(),
|
|
10
|
+
auth_type: z.enum(['api_key', 'gate']),
|
|
11
|
+
endpoint: z.string(),
|
|
12
|
+
active: z.boolean(),
|
|
13
|
+
created: z.string(),
|
|
14
|
+
})),
|
|
15
|
+
count: z.number().int().nonnegative(),
|
|
16
|
+
});
|
|
17
|
+
export default class AuthProfiles extends BaseCommand {
|
|
18
|
+
static errors = [ErrorCode.Internal];
|
|
19
|
+
static summary = 'List all stored profiles';
|
|
20
|
+
static description = 'List all stored auth profiles.';
|
|
21
|
+
static examples = ['<%= config.bin %> auth profiles', '<%= config.bin %> auth ls'];
|
|
22
|
+
static aliases = ['auth ls', 'auth list'];
|
|
23
|
+
static enableJsonFlag = true;
|
|
24
|
+
static strict = true;
|
|
25
|
+
static flags = {};
|
|
26
|
+
async execute() {
|
|
27
|
+
await this.parseFlags(AuthProfiles);
|
|
28
|
+
return authProfiles();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=profiles.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
import { authStatus } from '../../services/auth.js';
|
|
4
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
5
|
+
export const AuthStatusDataSchema = z.object({
|
|
6
|
+
authenticated: z.literal(true),
|
|
7
|
+
profile: z.string(),
|
|
8
|
+
auth_type: z.enum(['api_key', 'gate']),
|
|
9
|
+
endpoint: z.string(),
|
|
10
|
+
key: z.string().optional(),
|
|
11
|
+
config_path: z.string().optional(),
|
|
12
|
+
});
|
|
13
|
+
export default class AuthStatus extends BaseCommand {
|
|
14
|
+
static errors = [ErrorCode.AuthRequired];
|
|
15
|
+
static summary = 'Show current profile and auth state';
|
|
16
|
+
static description = 'Show the active auth profile and credential type.';
|
|
17
|
+
static examples = ['<%= config.bin %> auth status', '<%= config.bin %> auth whoami'];
|
|
18
|
+
static aliases = ['auth s', 'auth whoami'];
|
|
19
|
+
static enableJsonFlag = true;
|
|
20
|
+
static strict = true;
|
|
21
|
+
static flags = {};
|
|
22
|
+
async execute() {
|
|
23
|
+
await this.parseFlags(AuthStatus);
|
|
24
|
+
return authStatus();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import { authSwitch } from '../../services/auth.js';
|
|
5
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
6
|
+
export const AuthSwitchDataSchema = z.object({ active_profile: z.string() });
|
|
7
|
+
export default class AuthSwitch extends BaseCommand {
|
|
8
|
+
static errors = [ErrorCode.AuthProfileNotFound, ErrorCode.UsageRequired];
|
|
9
|
+
static summary = 'Switch the active profile';
|
|
10
|
+
static description = 'Switch the active auth profile.';
|
|
11
|
+
static examples = ['<%= config.bin %> auth switch work', '<%= config.bin %> auth use work'];
|
|
12
|
+
static aliases = ['auth use'];
|
|
13
|
+
static enableJsonFlag = true;
|
|
14
|
+
static strict = true;
|
|
15
|
+
static flags = {};
|
|
16
|
+
static args = {
|
|
17
|
+
profile: Args.string({ description: 'Profile name.', required: true }),
|
|
18
|
+
};
|
|
19
|
+
async execute() {
|
|
20
|
+
const { args } = await this.parse(AuthSwitch);
|
|
21
|
+
return authSwitch(args.profile);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=switch.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
import { fetchDocs } from '../../services/docs.js';
|
|
4
|
+
import { DocsContentDataSchema } from './get.js';
|
|
5
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
6
|
+
export default class DocsFetch extends BaseCommand {
|
|
7
|
+
static errors = [ErrorCode.ApiUnauthorized, ErrorCode.ApiForbidden, ErrorCode.ApiRateLimited, ErrorCode.GateInvalidResponse, ErrorCode.NetworkError, ErrorCode.NetworkTimeout, ErrorCode.ServiceUnavailable, ErrorCode.DocsLibraryNotFound, ErrorCode.DocsFetchFailed];
|
|
8
|
+
static summary = 'Fetch docs by exact library ID';
|
|
9
|
+
static description = 'Fetch Context7 documentation by exact library ID.';
|
|
10
|
+
static examples = ['<%= config.bin %> docs fetch /facebook/react hooks', '<%= config.bin %> docs fetch /vercel/next.js actions --tokens 5000', '<%= config.bin %> d f /facebook/react hooks'];
|
|
11
|
+
static aliases = ['docs f', 'd fetch', 'd f'];
|
|
12
|
+
static flags = {
|
|
13
|
+
tokens: Flags.integer({ description: 'Max tokens to return.' }),
|
|
14
|
+
page: Flags.integer({ description: 'Page number (1-10).' }),
|
|
15
|
+
topic: Flags.string({ description: 'Focus on a topic.' }),
|
|
16
|
+
refresh: Flags.boolean({ description: 'Bypass cache.', default: false }),
|
|
17
|
+
};
|
|
18
|
+
static args = {
|
|
19
|
+
'library-id': Args.string({ description: 'Library ID (for example /facebook/react).', required: true }),
|
|
20
|
+
query: Args.string({ description: 'Documentation query.', required: true }),
|
|
21
|
+
};
|
|
22
|
+
static enableJsonFlag = true;
|
|
23
|
+
static strict = true;
|
|
24
|
+
async execute() {
|
|
25
|
+
const { args, flags } = await this.parse(DocsFetch);
|
|
26
|
+
return fetchDocs({
|
|
27
|
+
libraryId: args['library-id'],
|
|
28
|
+
query: args.query,
|
|
29
|
+
tokens: flags.tokens,
|
|
30
|
+
page: flags.page,
|
|
31
|
+
topic: flags.topic,
|
|
32
|
+
refresh: flags.refresh,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export { DocsContentDataSchema };
|
|
37
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import { writeStderr } from '../../io/io.js';
|
|
5
|
+
import { getDocs } from '../../services/docs.js';
|
|
6
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
7
|
+
export const DocsContentDataSchema = z.object({
|
|
8
|
+
operation: z.enum(['get', 'fetch']).optional(),
|
|
9
|
+
cached: z.boolean(),
|
|
10
|
+
library_id: z.string(),
|
|
11
|
+
query: z.string(),
|
|
12
|
+
content: z.string(),
|
|
13
|
+
});
|
|
14
|
+
export default class DocsGet extends BaseCommand {
|
|
15
|
+
static errors = [ErrorCode.ApiUnauthorized, ErrorCode.ApiForbidden, ErrorCode.ApiRateLimited, ErrorCode.GateInvalidResponse, ErrorCode.NetworkError, ErrorCode.NetworkTimeout, ErrorCode.ServiceUnavailable, ErrorCode.DocsLibraryNotFound, ErrorCode.DocsNoResults, ErrorCode.DocsFetchFailed];
|
|
16
|
+
static summary = 'Resolve a library and fetch docs in one shot';
|
|
17
|
+
static description = 'Resolve a library name to a Context7 library ID, then fetch documentation.';
|
|
18
|
+
static examples = ['<%= config.bin %> docs get react hooks', '<%= config.bin %> docs get next.js "app router" --tokens 5000', '<%= config.bin %> d g react "useEffect cleanup"'];
|
|
19
|
+
static aliases = ['docs g', 'd get', 'd g'];
|
|
20
|
+
static flags = {
|
|
21
|
+
tokens: Flags.integer({ description: 'Max tokens to return.' }),
|
|
22
|
+
page: Flags.integer({ description: 'Page number (1-10).' }),
|
|
23
|
+
topic: Flags.string({ description: 'Focus on a topic.' }),
|
|
24
|
+
refresh: Flags.boolean({ description: 'Bypass cache.', default: false }),
|
|
25
|
+
};
|
|
26
|
+
static args = {
|
|
27
|
+
library: Args.string({ description: 'Library name.', required: true }),
|
|
28
|
+
query: Args.string({ description: 'Documentation query.', required: true }),
|
|
29
|
+
};
|
|
30
|
+
static enableJsonFlag = true;
|
|
31
|
+
static strict = true;
|
|
32
|
+
async execute() {
|
|
33
|
+
const { args, flags } = await this.parse(DocsGet);
|
|
34
|
+
const data = await getDocs({
|
|
35
|
+
libraryName: args.library,
|
|
36
|
+
query: args.query,
|
|
37
|
+
tokens: flags.tokens,
|
|
38
|
+
page: flags.page,
|
|
39
|
+
topic: flags.topic,
|
|
40
|
+
refresh: flags.refresh,
|
|
41
|
+
});
|
|
42
|
+
if (!flags.quiet && !flags.json)
|
|
43
|
+
await writeStderr(` → resolved: ${data.library_id}\n`);
|
|
44
|
+
return data;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=get.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
import { buildUsageError } from '../../lib/envelope.js';
|
|
3
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
4
|
+
export default class DocsTopic extends BaseCommand {
|
|
5
|
+
static errors = [ErrorCode.UsageInvalid];
|
|
6
|
+
static summary = 'Search and fetch library documentation';
|
|
7
|
+
static description = 'Use docs search, docs get, or docs fetch.';
|
|
8
|
+
static examples = ['<%= config.bin %> docs search react', '<%= config.bin %> docs get react hooks', '<%= config.bin %> docs fetch /facebook/react hooks'];
|
|
9
|
+
static aliases = ['d'];
|
|
10
|
+
static flags = {};
|
|
11
|
+
static args = {};
|
|
12
|
+
static enableJsonFlag = true;
|
|
13
|
+
static strict = true;
|
|
14
|
+
async execute() {
|
|
15
|
+
throw buildUsageError('usage: escli docs <search|get|fetch>');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import { renderDocsSearch, renderDocsSearchTsv, writeStdout, writeStderr } from '../../io/io.js';
|
|
5
|
+
import { searchDocs } from '../../services/docs.js';
|
|
6
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
7
|
+
export const DocsSearchResultSchema = z.object({
|
|
8
|
+
id: z.string(),
|
|
9
|
+
title: z.string(),
|
|
10
|
+
state: z.string().optional(),
|
|
11
|
+
stars: z.number().optional(),
|
|
12
|
+
description: z.string().optional(),
|
|
13
|
+
});
|
|
14
|
+
export const DocsSearchDataSchema = z.object({
|
|
15
|
+
operation: z.literal('search').optional(),
|
|
16
|
+
cached: z.boolean(),
|
|
17
|
+
results: z.array(DocsSearchResultSchema),
|
|
18
|
+
count: z.number().int().nonnegative(),
|
|
19
|
+
});
|
|
20
|
+
export default class DocsSearch extends BaseCommand {
|
|
21
|
+
static errors = [ErrorCode.ApiUnauthorized, ErrorCode.ApiForbidden, ErrorCode.ApiRateLimited, ErrorCode.GateInvalidResponse, ErrorCode.NetworkError, ErrorCode.NetworkTimeout, ErrorCode.ServiceUnavailable, ErrorCode.DocsLibraryNotFound, ErrorCode.DocsFetchFailed];
|
|
22
|
+
static summary = 'Search for libraries by name';
|
|
23
|
+
static description = 'Search Context7 for library documentation IDs.';
|
|
24
|
+
static examples = ['<%= config.bin %> docs search react', '<%= config.bin %> docs search react hooks --limit 2', '<%= config.bin %> d s next.js'];
|
|
25
|
+
static aliases = ['docs s', 'd search', 'd s'];
|
|
26
|
+
static flags = {
|
|
27
|
+
limit: Flags.integer({ description: 'Max results.', default: 10 }),
|
|
28
|
+
refresh: Flags.boolean({ description: 'Bypass cache.', default: false }),
|
|
29
|
+
};
|
|
30
|
+
static args = {
|
|
31
|
+
library: Args.string({ description: 'Library name.', required: true }),
|
|
32
|
+
query: Args.string({ description: 'Optional search query.', required: false }),
|
|
33
|
+
};
|
|
34
|
+
static enableJsonFlag = true;
|
|
35
|
+
static strict = true;
|
|
36
|
+
async execute() {
|
|
37
|
+
const { args, flags } = await this.parse(DocsSearch);
|
|
38
|
+
const data = await searchDocs({
|
|
39
|
+
libraryName: args.library,
|
|
40
|
+
query: args.query,
|
|
41
|
+
limit: flags.limit,
|
|
42
|
+
refresh: flags.refresh,
|
|
43
|
+
});
|
|
44
|
+
if (flags.quiet && !flags.json) {
|
|
45
|
+
await writeStdout(renderDocsSearchTsv(data));
|
|
46
|
+
this.humanOutputHandled = true;
|
|
47
|
+
}
|
|
48
|
+
else if (!flags.json) {
|
|
49
|
+
await writeStderr(renderDocsSearch(data));
|
|
50
|
+
this.humanOutputHandled = true;
|
|
51
|
+
}
|
|
52
|
+
return data;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { BaseCommand } from '../base-command.js';
|
|
4
|
+
import { writeStderr } from '../io/io.js';
|
|
5
|
+
import { fetchUrls } from '../services/fetch.js';
|
|
6
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
7
|
+
export const FetchResultSchema = z.object({
|
|
8
|
+
title: z.string().nullable().optional(),
|
|
9
|
+
url: z.string(),
|
|
10
|
+
excerpts: z.array(z.string()).default([]),
|
|
11
|
+
full_content: z.string().nullable().optional(),
|
|
12
|
+
publish_date: z.string().nullable().optional(),
|
|
13
|
+
}).passthrough();
|
|
14
|
+
export const FetchDataSchema = z.object({
|
|
15
|
+
elapsed_seconds: z.number().nonnegative().optional(),
|
|
16
|
+
results: z.array(FetchResultSchema),
|
|
17
|
+
count: z.number().int().nonnegative(),
|
|
18
|
+
});
|
|
19
|
+
export default class Fetch extends BaseCommand {
|
|
20
|
+
static errors = [ErrorCode.UsageRequired, ErrorCode.ApiUnauthorized, ErrorCode.ApiForbidden, ErrorCode.ApiRateLimited, ErrorCode.FileNotFound, ErrorCode.GateInvalidResponse, ErrorCode.JsonInvalid, ErrorCode.NetworkError, ErrorCode.NetworkTimeout, ErrorCode.ServiceUnavailable, ErrorCode.FetchFailed];
|
|
21
|
+
static summary = 'Extract clean content from URLs';
|
|
22
|
+
static description = 'Extract clean content from URLs via Parallel Extract.';
|
|
23
|
+
static examples = [
|
|
24
|
+
'<%= config.bin %> fetch https://docs.parallel.ai/search/search-quickstart',
|
|
25
|
+
'<%= config.bin %> fetch https://example.com --objective "pricing information"',
|
|
26
|
+
'<%= config.bin %> fetch https://example.com --full',
|
|
27
|
+
'<%= config.bin %> --json fetch https://example.com https://other.com',
|
|
28
|
+
];
|
|
29
|
+
static aliases = ['f'];
|
|
30
|
+
static flags = {
|
|
31
|
+
objective: Flags.string({ description: 'Focus on this topic.' }),
|
|
32
|
+
full: Flags.boolean({ description: 'Return full content instead of excerpts.', default: false }),
|
|
33
|
+
};
|
|
34
|
+
static args = {
|
|
35
|
+
urls: Args.string({ description: 'URLs to extract.', required: true, multiple: true }),
|
|
36
|
+
};
|
|
37
|
+
static enableJsonFlag = true;
|
|
38
|
+
static strict = true;
|
|
39
|
+
async execute() {
|
|
40
|
+
const { args, flags } = await this.parse(Fetch);
|
|
41
|
+
const urls = args.urls;
|
|
42
|
+
if (!flags.quiet && !flags.json)
|
|
43
|
+
await writeStderr(` ▸ fetching ${urls.length} URL(s)...\n`);
|
|
44
|
+
const data = await fetchUrls({
|
|
45
|
+
urls,
|
|
46
|
+
objective: flags.objective,
|
|
47
|
+
full: flags.full,
|
|
48
|
+
timeoutSeconds: flags.timeout,
|
|
49
|
+
});
|
|
50
|
+
if (!flags.quiet && !flags.json)
|
|
51
|
+
await writeStderr(` ${data.count} page(s) · ${data.elapsed_seconds}s\n`);
|
|
52
|
+
return data;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { BaseCommand } from '../../base-command.js';
|
|
3
|
+
import { writeStdout } from '../../io/io.js';
|
|
4
|
+
import { editImage } from '../../services/image.js';
|
|
5
|
+
import { ImageDataSchema } from './generate.js';
|
|
6
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
7
|
+
export const ImageEditDataSchema = ImageDataSchema;
|
|
8
|
+
export default class ImageEdit extends BaseCommand {
|
|
9
|
+
static errors = [ErrorCode.UsageRequired, ErrorCode.UsageInvalid, ErrorCode.UsageUnknownFlag, ErrorCode.ValidationFailed, ErrorCode.AuthRequired, ErrorCode.GateCredentialUnavailable, ErrorCode.ApiUnauthorized, ErrorCode.ApiForbidden, ErrorCode.ApiRateLimited, ErrorCode.ApiError, ErrorCode.NetworkError, ErrorCode.NetworkTimeout, ErrorCode.ServiceUnavailable, ErrorCode.GateInvalidResponse, ErrorCode.FileNotFound, ErrorCode.FileReadFailed, ErrorCode.FileWriteFailed, ErrorCode.ImagePromptRequired, ErrorCode.ImageSizeInvalid, ErrorCode.ImageEditFailed, ErrorCode.ImageOpenFailed];
|
|
10
|
+
static summary = 'Edit an existing image with a text prompt';
|
|
11
|
+
static description = 'Edit an existing image using a text instruction via the OpenAI-compatible image endpoint.';
|
|
12
|
+
static examples = ['<%= config.bin %> image edit "make it snow" -i summer.jpg', '<%= config.bin %> image edit "make it blue" -i input.png -o output.png', '<%= config.bin %> --json --quiet image edit "remove the background" -i product.png'];
|
|
13
|
+
static aliases = ['image e', 'img edit', 'img e', 'i edit', 'i e'];
|
|
14
|
+
static flags = {
|
|
15
|
+
input: Flags.string({ char: 'i', description: 'Input image path.', required: true }),
|
|
16
|
+
size: Flags.string({ char: 's', description: 'Size: sq|wide|tall or WxH.', default: process.env.ESCLI_IMAGE_SIZE ?? '1024x1024' }),
|
|
17
|
+
quality: Flags.string({ char: 'q', description: 'Quality.', options: ['low', 'medium', 'high'], default: process.env.ESCLI_IMAGE_QUALITY ?? 'high' }),
|
|
18
|
+
format: Flags.string({ char: 'f', description: 'Output format.', options: ['png', 'jpeg', 'jpg', 'webp'], default: process.env.ESCLI_IMAGE_FORMAT ?? 'png' }),
|
|
19
|
+
model: Flags.string({ char: 'm', description: 'Model.', default: process.env.ESCLI_IMAGE_MODEL ?? 'gpt-image-2' }),
|
|
20
|
+
output: Flags.string({ char: 'o', description: 'Output path.' }),
|
|
21
|
+
'out-dir': Flags.string({ char: 'd', description: 'Output directory.', default: process.env.ESCLI_OUT_DIR ?? '.' }),
|
|
22
|
+
open: Flags.boolean({ description: 'Open result after writing.', default: false }),
|
|
23
|
+
compression: Flags.integer({ description: 'JPEG/WebP compression 0-100.' }),
|
|
24
|
+
moderation: Flags.string({ description: 'Moderation.', options: ['auto', 'low'] }),
|
|
25
|
+
fidelity: Flags.string({ description: 'Fidelity to input.', options: ['low', 'high'] }),
|
|
26
|
+
};
|
|
27
|
+
static args = {
|
|
28
|
+
prompt: Args.string({ description: 'Edit instruction.', required: true, multiple: true }),
|
|
29
|
+
};
|
|
30
|
+
static enableJsonFlag = true;
|
|
31
|
+
static strict = true;
|
|
32
|
+
async execute() {
|
|
33
|
+
const { args, flags } = await this.parse(ImageEdit);
|
|
34
|
+
const options = {
|
|
35
|
+
prompt: args.prompt.join(' '),
|
|
36
|
+
input: flags.input,
|
|
37
|
+
size: flags.size,
|
|
38
|
+
quality: flags.quality,
|
|
39
|
+
format: flags.format,
|
|
40
|
+
model: flags.model,
|
|
41
|
+
output: flags.output,
|
|
42
|
+
outDir: flags['out-dir'],
|
|
43
|
+
compression: flags.compression,
|
|
44
|
+
moderation: flags.moderation,
|
|
45
|
+
fidelity: flags.fidelity,
|
|
46
|
+
apiKey: flags['api-key'],
|
|
47
|
+
baseUrl: flags['base-url'],
|
|
48
|
+
timeoutSeconds: flags.timeout,
|
|
49
|
+
};
|
|
50
|
+
const data = await editImage(options);
|
|
51
|
+
if (!flags.json) {
|
|
52
|
+
if (flags.quiet)
|
|
53
|
+
await writeStdout(`${data.path}\n`);
|
|
54
|
+
this.humanOutputHandled = true;
|
|
55
|
+
}
|
|
56
|
+
return data;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=edit.js.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { BaseCommand } from '../../base-command.js';
|
|
4
|
+
import { writeStdout } from '../../io/io.js';
|
|
5
|
+
import { generateImage } from '../../services/image.js';
|
|
6
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
7
|
+
export const ImageDataSchema = z.object({
|
|
8
|
+
path: z.string(),
|
|
9
|
+
size_bytes: z.number().int().positive(),
|
|
10
|
+
elapsed_seconds: z.number().nonnegative(),
|
|
11
|
+
prompt: z.string(),
|
|
12
|
+
input: z.string().optional(),
|
|
13
|
+
model: z.string(),
|
|
14
|
+
image_size: z.string(),
|
|
15
|
+
quality: z.string(),
|
|
16
|
+
revised_prompt: z.string().optional(),
|
|
17
|
+
});
|
|
18
|
+
export default class ImageGenerate extends BaseCommand {
|
|
19
|
+
static errors = [ErrorCode.UsageRequired, ErrorCode.UsageInvalid, ErrorCode.UsageUnknownFlag, ErrorCode.ValidationFailed, ErrorCode.AuthRequired, ErrorCode.GateCredentialUnavailable, ErrorCode.ApiUnauthorized, ErrorCode.ApiForbidden, ErrorCode.ApiRateLimited, ErrorCode.ApiError, ErrorCode.NetworkError, ErrorCode.NetworkTimeout, ErrorCode.ServiceUnavailable, ErrorCode.GateInvalidResponse, ErrorCode.FileWriteFailed, ErrorCode.ImagePromptRequired, ErrorCode.ImageSizeInvalid, ErrorCode.ImageGenerationFailed, ErrorCode.ImageOpenFailed];
|
|
20
|
+
static summary = 'Generate an image from a text prompt';
|
|
21
|
+
static description = 'Generate an image from a text prompt via the OpenAI-compatible image endpoint.';
|
|
22
|
+
static examples = ['<%= config.bin %> image generate "a sunset over the ocean"', '<%= config.bin %> image generate "logo design" -s wide -q high -o logo.png', '<%= config.bin %> --json --quiet image generate "a logo" -o /tmp/logo.png'];
|
|
23
|
+
static aliases = ['image gen', 'image g', 'img generate', 'img gen', 'img g', 'i generate', 'i gen', 'i g'];
|
|
24
|
+
static flags = {
|
|
25
|
+
size: Flags.string({ char: 's', description: 'Size: sq|wide|tall or WxH.', default: process.env.ESCLI_IMAGE_SIZE ?? '1024x1024' }),
|
|
26
|
+
quality: Flags.string({ char: 'q', description: 'Quality.', options: ['low', 'medium', 'high'], default: process.env.ESCLI_IMAGE_QUALITY ?? 'high' }),
|
|
27
|
+
format: Flags.string({ char: 'f', description: 'Output format.', options: ['png', 'jpeg', 'jpg', 'webp'], default: process.env.ESCLI_IMAGE_FORMAT ?? 'png' }),
|
|
28
|
+
model: Flags.string({ char: 'm', description: 'Model.', default: process.env.ESCLI_IMAGE_MODEL ?? 'gpt-image-2' }),
|
|
29
|
+
output: Flags.string({ char: 'o', description: 'Output path.' }),
|
|
30
|
+
'out-dir': Flags.string({ char: 'd', description: 'Output directory.', default: process.env.ESCLI_OUT_DIR ?? '.' }),
|
|
31
|
+
open: Flags.boolean({ description: 'Open result after writing.', default: false }),
|
|
32
|
+
compression: Flags.integer({ description: 'JPEG/WebP compression 0-100.' }),
|
|
33
|
+
moderation: Flags.string({ description: 'Moderation.', options: ['auto', 'low'] }),
|
|
34
|
+
background: Flags.string({ description: 'Background.', options: ['auto', 'transparent'] }),
|
|
35
|
+
};
|
|
36
|
+
static args = {
|
|
37
|
+
prompt: Args.string({ description: 'Text prompt.', required: true, multiple: true }),
|
|
38
|
+
};
|
|
39
|
+
static enableJsonFlag = true;
|
|
40
|
+
static strict = true;
|
|
41
|
+
async execute() {
|
|
42
|
+
const { args, flags } = await this.parse(ImageGenerate);
|
|
43
|
+
const options = {
|
|
44
|
+
prompt: args.prompt.join(' '),
|
|
45
|
+
size: flags.size,
|
|
46
|
+
quality: flags.quality,
|
|
47
|
+
format: flags.format,
|
|
48
|
+
model: flags.model,
|
|
49
|
+
output: flags.output,
|
|
50
|
+
outDir: flags['out-dir'],
|
|
51
|
+
compression: flags.compression,
|
|
52
|
+
moderation: flags.moderation,
|
|
53
|
+
background: flags.background,
|
|
54
|
+
apiKey: flags['api-key'],
|
|
55
|
+
baseUrl: flags['base-url'],
|
|
56
|
+
timeoutSeconds: flags.timeout,
|
|
57
|
+
};
|
|
58
|
+
const data = await generateImage(options);
|
|
59
|
+
if (!flags.json) {
|
|
60
|
+
if (flags.quiet)
|
|
61
|
+
await writeStdout(`${data.path}\n`);
|
|
62
|
+
this.humanOutputHandled = true;
|
|
63
|
+
}
|
|
64
|
+
return data;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command.js';
|
|
2
|
+
import { buildUsageError } from '../../lib/envelope.js';
|
|
3
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
4
|
+
export default class ImageTopic extends BaseCommand {
|
|
5
|
+
static errors = [ErrorCode.UsageInvalid];
|
|
6
|
+
static summary = 'Generate or edit images from prompts';
|
|
7
|
+
static description = 'Use image generate or image edit.';
|
|
8
|
+
static examples = ['<%= config.bin %> image generate "a sunset"', '<%= config.bin %> image edit "make it blue" -i input.png'];
|
|
9
|
+
static aliases = ['img', 'i'];
|
|
10
|
+
static flags = {};
|
|
11
|
+
static args = {};
|
|
12
|
+
static enableJsonFlag = true;
|
|
13
|
+
static strict = true;
|
|
14
|
+
async execute() {
|
|
15
|
+
throw buildUsageError('usage: escli image <generate|edit>');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { BaseCommand } from '../base-command.js';
|
|
3
|
+
import { listModels } from '../services/models.js';
|
|
4
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
5
|
+
export const ModelsDataSchema = z.object({
|
|
6
|
+
models: z.array(z.string()),
|
|
7
|
+
count: z.number().int().nonnegative(),
|
|
8
|
+
});
|
|
9
|
+
export default class Models extends BaseCommand {
|
|
10
|
+
static errors = [ErrorCode.AuthRequired, ErrorCode.ApiUnauthorized, ErrorCode.ApiForbidden, ErrorCode.ApiRateLimited, ErrorCode.ApiError, ErrorCode.NetworkError, ErrorCode.NetworkTimeout, ErrorCode.ServiceUnavailable, ErrorCode.ModelsListFailed];
|
|
11
|
+
static summary = 'List models available on the endpoint';
|
|
12
|
+
static description = 'List all models available on the API endpoint.';
|
|
13
|
+
static examples = ['<%= config.bin %> models', '<%= config.bin %> --json models'];
|
|
14
|
+
static aliases = ['m'];
|
|
15
|
+
static flags = {};
|
|
16
|
+
static enableJsonFlag = true;
|
|
17
|
+
static strict = true;
|
|
18
|
+
async execute() {
|
|
19
|
+
const flags = await this.parseFlags(Models);
|
|
20
|
+
return listModels({
|
|
21
|
+
apiKey: flags['api-key'],
|
|
22
|
+
baseUrl: flags['base-url'],
|
|
23
|
+
timeoutSeconds: flags.timeout,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { ErrorCode } from '@eightstate/contracts/errors';
|
|
4
|
+
import { ExitCodes } from '@eightstate/contracts/exit-codes';
|
|
5
|
+
import { BaseCommand } from '../base-command.js';
|
|
6
|
+
import { EscliError } from '../lib/escli-error.js';
|
|
7
|
+
import { writeStderr } from '../io/io.js';
|
|
8
|
+
import { listResearchProcessors, PROCESSORS, runResearch, getResearchResult, getResearchStatus } from '../services/research.js';
|
|
9
|
+
export const ResearchProcessorSchema = z.object({
|
|
10
|
+
name: z.string(),
|
|
11
|
+
});
|
|
12
|
+
export const ResearchOutputSchema = z.object({
|
|
13
|
+
content: z.unknown().optional(),
|
|
14
|
+
basis: z.array(z.unknown()).optional(),
|
|
15
|
+
}).nullable();
|
|
16
|
+
export const ResearchDataSchema = z.union([
|
|
17
|
+
z.object({ processors: z.array(ResearchProcessorSchema), count: z.number().int().nonnegative() }),
|
|
18
|
+
z.object({ run_id: z.string(), processor: z.string(), output: ResearchOutputSchema, path: z.string().optional() }),
|
|
19
|
+
z.object({ run_id: z.string(), status: z.string(), error: z.unknown().optional(), warnings: z.array(z.unknown()).optional() }),
|
|
20
|
+
z.object({ run_id: z.string(), output: ResearchOutputSchema, path: z.string().optional() }),
|
|
21
|
+
]);
|
|
22
|
+
export default class Research extends BaseCommand {
|
|
23
|
+
static errors = [ErrorCode.UsageRequired, ErrorCode.UsageInvalid, ErrorCode.UsageUnknownFlag, ErrorCode.FileNotFound, ErrorCode.FileReadFailed, ErrorCode.FileWriteFailed, ErrorCode.ApiUnauthorized, ErrorCode.ApiForbidden, ErrorCode.ApiRateLimited, ErrorCode.GateInvalidResponse, ErrorCode.NetworkError, ErrorCode.NetworkTimeout, ErrorCode.ServiceUnavailable, ErrorCode.ResearchInputInvalid, ErrorCode.ResearchTaskFailed, ErrorCode.ResearchRunNotFound, ErrorCode.ResearchTimeout, ErrorCode.ResearchApiKeyMissing];
|
|
24
|
+
static summary = 'Run deep web research tasks';
|
|
25
|
+
static description = 'Run Parallel Task API research tasks, list processors, check status, or fetch completed results.';
|
|
26
|
+
static examples = [
|
|
27
|
+
'<%= config.bin %> research "HVAC industry market report" -o hvac.md',
|
|
28
|
+
'<%= config.bin %> research "Stripe" --output-schema "founding year and total funding" -p base',
|
|
29
|
+
'<%= config.bin %> research --processors',
|
|
30
|
+
'<%= config.bin %> research --status trun_xxx',
|
|
31
|
+
'<%= config.bin %> research --result trun_xxx -o out.md',
|
|
32
|
+
];
|
|
33
|
+
static aliases = ['r'];
|
|
34
|
+
static flags = {
|
|
35
|
+
processors: Flags.boolean({ description: 'List available processor tiers.', default: false }),
|
|
36
|
+
status: Flags.string({ description: 'Check task run status.' }),
|
|
37
|
+
result: Flags.string({ description: 'Fetch completed task result.' }),
|
|
38
|
+
output: Flags.string({ char: 'o', description: 'Output path.' }),
|
|
39
|
+
processor: Flags.string({ char: 'p', description: 'Processor tier.', options: [...PROCESSORS], default: 'pro' }),
|
|
40
|
+
text: Flags.boolean({ description: 'Request text output schema.', default: false }),
|
|
41
|
+
schema: Flags.string({ description: 'JSON Schema file for structured output.' }),
|
|
42
|
+
'output-schema': Flags.string({ description: 'Inline schema description.' }),
|
|
43
|
+
'input-json': Flags.string({ description: 'JSON input instead of text.' }),
|
|
44
|
+
'input-file': Flags.string({ description: 'JSON input file.' }),
|
|
45
|
+
'include-domains': Flags.string({ description: 'Only use these domains, comma-separated.' }),
|
|
46
|
+
'exclude-domains': Flags.string({ description: 'Exclude these domains, comma-separated.' }),
|
|
47
|
+
'after-date': Flags.string({ description: 'Filter content after this date.' }),
|
|
48
|
+
location: Flags.string({ description: 'ISO country code for geo-targeting.' }),
|
|
49
|
+
metadata: Flags.string({ description: 'Metadata as JSON or key=val,key=val.' }),
|
|
50
|
+
'follow-up': Flags.string({ description: 'Follow up on a previous run.' }),
|
|
51
|
+
'no-basis': Flags.boolean({ description: 'Exclude citations and reasoning from human/file output.', default: false }),
|
|
52
|
+
};
|
|
53
|
+
static args = {
|
|
54
|
+
query: Args.string({ description: 'Research question or topic.', required: false, multiple: true }),
|
|
55
|
+
};
|
|
56
|
+
static enableJsonFlag = true;
|
|
57
|
+
static strict = true;
|
|
58
|
+
async execute() {
|
|
59
|
+
const { args, flags } = await this.parse(Research);
|
|
60
|
+
if (flags.processors)
|
|
61
|
+
return listResearchProcessors();
|
|
62
|
+
if (flags.status)
|
|
63
|
+
return getResearchStatus({ runId: flags.status, timeoutSeconds: flags.timeout });
|
|
64
|
+
if (flags.result)
|
|
65
|
+
return getResearchResult({ runId: flags.result, output: flags.output, noBasis: flags['no-basis'], timeoutSeconds: flags.timeout });
|
|
66
|
+
const query = args.query?.join(' ').trim() ?? '';
|
|
67
|
+
if (!query)
|
|
68
|
+
throw new EscliError('usage: escli research "query" -o output.md', { code: ErrorCode.UsageRequired, exitCode: ExitCodes.Usage });
|
|
69
|
+
if (!flags.quiet && !flags.json)
|
|
70
|
+
await writeStderr(` ▸ submitting task (processor=${flags.processor})...\n`);
|
|
71
|
+
return runResearch({
|
|
72
|
+
query,
|
|
73
|
+
processor: flags.processor,
|
|
74
|
+
output: flags.output,
|
|
75
|
+
text: flags.text,
|
|
76
|
+
schema: flags.schema,
|
|
77
|
+
outputSchema: flags['output-schema'],
|
|
78
|
+
inputJson: flags['input-json'],
|
|
79
|
+
inputFile: flags['input-file'],
|
|
80
|
+
includeDomains: flags['include-domains'],
|
|
81
|
+
excludeDomains: flags['exclude-domains'],
|
|
82
|
+
afterDate: flags['after-date'],
|
|
83
|
+
location: flags.location,
|
|
84
|
+
metadata: flags.metadata,
|
|
85
|
+
followUp: flags['follow-up'],
|
|
86
|
+
noBasis: flags['no-basis'],
|
|
87
|
+
quiet: flags.quiet || flags.json,
|
|
88
|
+
timeoutSeconds: flags.timeout,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=research.js.map
|