@sixb/cli-core 0.1.7 → 0.1.9
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/dist/api-client.d.ts +6 -2
- package/dist/api-client.d.ts.map +1 -1
- package/dist/arguments.d.ts +4 -2
- package/dist/arguments.d.ts.map +1 -1
- package/dist/commands/actions.d.ts +3 -1
- package/dist/commands/actions.d.ts.map +1 -1
- package/dist/commands/index.d.ts +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/metadata.d.ts +6 -3
- package/dist/commands/metadata.d.ts.map +1 -1
- package/dist/commands/models.d.ts +79 -0
- package/dist/commands/models.d.ts.map +1 -0
- package/dist/commands/objects.d.ts.map +1 -1
- package/dist/commands/shared.d.ts +2 -0
- package/dist/commands/shared.d.ts.map +1 -1
- package/dist/commands/users.d.ts +3 -0
- package/dist/commands/users.d.ts.map +1 -0
- package/dist/commands/workflows.d.ts.map +1 -1
- package/dist/index.js +561 -63
- package/dist/index.js.map +16 -14
- package/dist/output.d.ts +12 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/policies.d.ts +5 -0
- package/dist/policies.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api-client.ts +22 -4
- package/src/arguments.ts +18 -6
- package/src/commands/actions.ts +43 -41
- package/src/commands/index.ts +8 -0
- package/src/commands/metadata.ts +80 -8
- package/src/commands/models.ts +508 -0
- package/src/commands/objects.ts +47 -2
- package/src/commands/runs.ts +1 -1
- package/src/commands/shared.ts +11 -7
- package/src/commands/users.ts +67 -0
- package/src/commands/workflows.ts +10 -4
- package/src/output.ts +21 -0
- package/src/policies.ts +2 -0
package/dist/output.d.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export declare const INSTANCE_CLI_VERSION = "1";
|
|
3
3
|
export declare const EXIT_USAGE = 2;
|
|
4
4
|
export declare const EXIT_API = 3;
|
|
5
|
+
/** The request waits for its user's approval: it did not run. */
|
|
6
|
+
export declare const EXIT_AWAITING_APPROVAL = 4;
|
|
5
7
|
export interface CliErrorBody {
|
|
6
8
|
readonly code: string;
|
|
7
9
|
readonly status?: number;
|
|
@@ -16,6 +18,16 @@ export declare class CliError extends Error {
|
|
|
16
18
|
}
|
|
17
19
|
export declare function fail(message: string, code?: string, hint?: string): never;
|
|
18
20
|
export declare function writeJson(value: unknown): void;
|
|
21
|
+
/** Ends a command that already wrote its output, with an exit code that is not a success. */
|
|
22
|
+
export declare class CliExit extends Error {
|
|
23
|
+
readonly exitCode: number;
|
|
24
|
+
constructor(exitCode: number);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Print what a request that changes state answered. A request held for the user's approval prints
|
|
28
|
+
* as the API answered it, and exits with {@link EXIT_AWAITING_APPROVAL}: `a && b` does not run `b`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function writeRequestResult(value: unknown): void;
|
|
19
31
|
export declare function writeText(value: string): void;
|
|
20
32
|
export declare function reportError(error: unknown): number;
|
|
21
33
|
//# sourceMappingURL=output.d.ts.map
|
package/dist/output.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,eAAO,MAAM,oBAAoB,MAAM,CAAA;AACvC,eAAO,MAAM,UAAU,IAAI,CAAA;AAC3B,eAAO,MAAM,QAAQ,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,eAAO,MAAM,oBAAoB,MAAM,CAAA;AACvC,eAAO,MAAM,UAAU,IAAI,CAAA;AAC3B,eAAO,MAAM,QAAQ,IAAI,CAAA;AACzB,iEAAiE;AACjE,eAAO,MAAM,sBAAsB,IAAI,CAAA;AAEvC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;CACrC;AAED,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;gBAEb,IAAI,EAAE,YAAY,EAAE,QAAQ,SAAa;CAMtD;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAsB,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAEtF;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE9C;AAED,6FAA6F;AAC7F,qBAAa,OAAQ,SAAQ,KAAK;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM;gBAAhB,QAAQ,EAAE,MAAM;CAItC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAIvD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAclD"}
|
package/dist/policies.d.ts
CHANGED
|
@@ -20,6 +20,11 @@ export declare const CLI_LIMITS: {
|
|
|
20
20
|
readonly default: 100;
|
|
21
21
|
readonly maximum: 1000;
|
|
22
22
|
};
|
|
23
|
+
/** The server lists at most 200 members per page. */
|
|
24
|
+
readonly users: {
|
|
25
|
+
readonly default: 20;
|
|
26
|
+
readonly maximum: 200;
|
|
27
|
+
};
|
|
23
28
|
readonly inspect: {
|
|
24
29
|
readonly depth: {
|
|
25
30
|
readonly default: 2;
|
package/dist/policies.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policies.d.ts","sourceRoot":"","sources":["../src/policies.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,eAAO,MAAM,UAAU;;;;;;;;;IAGrB,+FAA+F
|
|
1
|
+
{"version":3,"file":"policies.d.ts","sourceRoot":"","sources":["../src/policies.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,eAAO,MAAM,UAAU;;;;;;;;;IAGrB,+FAA+F;;;;;;;;;;;;IAI/F,qDAAqD;;;;;;;;;;;;;;;;;;;;CAQ7C,CAAA;AAEV,eAAO,MAAM,kBAAkB,EAAG,MAAe,CAAA;AACjD,eAAO,MAAM,uBAAuB,EAAG,WAAoB,CAAA;AAC3D,eAAO,MAAM,uBAAuB,EAAG,MAAe,CAAA"}
|
package/package.json
CHANGED
package/src/api-client.ts
CHANGED
|
@@ -27,17 +27,34 @@ export class ApiClient {
|
|
|
27
27
|
return this.json(url, { method: "GET" })
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
/** `signal` stops waiting for the response; the abort is rethrown as it was raised. */
|
|
31
|
+
async post(
|
|
32
|
+
path: string,
|
|
33
|
+
body: unknown,
|
|
34
|
+
options: { readonly signal?: AbortSignal } = {}
|
|
35
|
+
): Promise<unknown> {
|
|
31
36
|
return this.json(this.url(path), {
|
|
32
37
|
method: "POST",
|
|
33
38
|
headers: { "content-type": "application/json" },
|
|
34
39
|
body: JSON.stringify(body),
|
|
40
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
35
41
|
})
|
|
36
42
|
}
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
/** `mediaType` labels the part; without it, the server reads the type from the file name. */
|
|
45
|
+
async upload(
|
|
46
|
+
path: string,
|
|
47
|
+
source: string,
|
|
48
|
+
logicalPath?: string,
|
|
49
|
+
mediaType?: string
|
|
50
|
+
): Promise<unknown> {
|
|
39
51
|
const form = new FormData()
|
|
40
|
-
|
|
52
|
+
const bytes = new Uint8Array(await readFile(source))
|
|
53
|
+
form.append(
|
|
54
|
+
"file",
|
|
55
|
+
new Blob([bytes], mediaType ? { type: mediaType } : undefined),
|
|
56
|
+
basename(source)
|
|
57
|
+
)
|
|
41
58
|
if (logicalPath) form.append("logicalPath", logicalPath)
|
|
42
59
|
return this.json(this.url(path), { method: "POST", body: form })
|
|
43
60
|
}
|
|
@@ -91,7 +108,8 @@ export class ApiClient {
|
|
|
91
108
|
const headers = new Headers(init.headers)
|
|
92
109
|
if (this.authorization) headers.set("authorization", this.authorization)
|
|
93
110
|
response = await fetch(url, { ...init, headers })
|
|
94
|
-
} catch {
|
|
111
|
+
} catch (error) {
|
|
112
|
+
if (init.signal?.aborted) throw error
|
|
95
113
|
throw new CliError(
|
|
96
114
|
{
|
|
97
115
|
code: "api_unreachable",
|
package/src/arguments.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { fail } from "./output"
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/** `strings` may repeat, and collects every value in order. */
|
|
4
|
+
type OptionKinds = Readonly<Record<string, "string" | "strings" | "boolean">>
|
|
5
|
+
|
|
6
|
+
type OptionValue<TKind> = TKind extends "boolean"
|
|
7
|
+
? boolean
|
|
8
|
+
: TKind extends "strings"
|
|
9
|
+
? string[]
|
|
10
|
+
: string
|
|
4
11
|
|
|
5
12
|
/** Parse a command's options once, before reading files or calling the API. */
|
|
6
13
|
export function parseCommandArgs<const T extends OptionKinds>(
|
|
@@ -10,10 +17,10 @@ export function parseCommandArgs<const T extends OptionKinds>(
|
|
|
10
17
|
positionalCount: number | readonly [number, number] = 0
|
|
11
18
|
): {
|
|
12
19
|
positionals: string[]
|
|
13
|
-
options: { [K in keyof T]?: T[K]
|
|
20
|
+
options: { [K in keyof T]?: OptionValue<T[K]> }
|
|
14
21
|
} {
|
|
15
22
|
const positionals: string[] = []
|
|
16
|
-
const options: Record<string, string | boolean> = {}
|
|
23
|
+
const options: Record<string, string | string[] | boolean> = {}
|
|
17
24
|
let positionalOnly = false
|
|
18
25
|
for (let index = 0; index < args.length; index++) {
|
|
19
26
|
const argument = args[index] ?? ""
|
|
@@ -28,7 +35,9 @@ export function parseCommandArgs<const T extends OptionKinds>(
|
|
|
28
35
|
const equals = argument.indexOf("=")
|
|
29
36
|
const flag = equals < 0 ? argument : argument.slice(0, equals)
|
|
30
37
|
if (!Object.hasOwn(kinds, flag)) fail(`Unknown ${command} option '${flag}'.`)
|
|
31
|
-
if (Object.hasOwn(options, flag)
|
|
38
|
+
if (Object.hasOwn(options, flag) && kinds[flag] !== "strings") {
|
|
39
|
+
fail(`${flag} may only be provided once.`)
|
|
40
|
+
}
|
|
32
41
|
if (kinds[flag] === "boolean") {
|
|
33
42
|
if (equals >= 0) fail(`${flag} does not accept a value.`)
|
|
34
43
|
options[flag] = true
|
|
@@ -37,7 +46,9 @@ export function parseCommandArgs<const T extends OptionKinds>(
|
|
|
37
46
|
if (!value || (equals < 0 && value.startsWith("--"))) {
|
|
38
47
|
fail(`${flag} requires a value.`)
|
|
39
48
|
}
|
|
40
|
-
options[flag]
|
|
49
|
+
const previous = options[flag]
|
|
50
|
+
options[flag] =
|
|
51
|
+
kinds[flag] === "strings" ? [...(Array.isArray(previous) ? previous : []), value] : value
|
|
41
52
|
}
|
|
42
53
|
}
|
|
43
54
|
const [minimum, maximum] =
|
|
@@ -48,7 +59,7 @@ export function parseCommandArgs<const T extends OptionKinds>(
|
|
|
48
59
|
return {
|
|
49
60
|
positionals,
|
|
50
61
|
// Every assigned option was checked against its declared kind above.
|
|
51
|
-
options: options as { [K in keyof T]?: T[K]
|
|
62
|
+
options: options as { [K in keyof T]?: OptionValue<T[K]> },
|
|
52
63
|
}
|
|
53
64
|
}
|
|
54
65
|
|
|
@@ -126,5 +137,6 @@ export function enumValue<const T extends readonly string[]>(
|
|
|
126
137
|
|
|
127
138
|
function formatAlternatives(values: readonly string[]): string {
|
|
128
139
|
if (values.length < 2) return values[0] ?? "a supported value"
|
|
140
|
+
if (values.length === 2) return `${values[0]} or ${values[1]}`
|
|
129
141
|
return `${values.slice(0, -1).join(", ")}, or ${values.at(-1)}`
|
|
130
142
|
}
|
package/src/commands/actions.ts
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto"
|
|
1
2
|
import type { ApiClient } from "../api-client"
|
|
2
3
|
import { isHelp, parseCommandArgs, requestsHelp } from "../arguments"
|
|
3
|
-
import { CliError, EXIT_API, fail, writeJson, writeText } from "../output"
|
|
4
|
+
import { CliError, EXIT_API, fail, writeJson, writeRequestResult, writeText } from "../output"
|
|
4
5
|
import { GROUP_HELP } from "./metadata"
|
|
5
6
|
import { asRecord, parseQueryOptions, readJson } from "./shared"
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
/**
|
|
9
|
+
* How long `actions request` waits for the run it requested. An agent's command is killed after 30
|
|
10
|
+
* seconds, which is also how long an Action has to reach its boundary: stopping first leaves the
|
|
11
|
+
* agent with the run id, instead of a dead command and a request it can only repeat.
|
|
12
|
+
*/
|
|
13
|
+
const ACTION_REQUEST_WAIT_MS = 25_000
|
|
14
|
+
|
|
15
|
+
export async function actions(
|
|
16
|
+
api: ApiClient,
|
|
17
|
+
args: readonly string[],
|
|
18
|
+
/** Test-only override of {@link ACTION_REQUEST_WAIT_MS}. */
|
|
19
|
+
requestWaitMs = ACTION_REQUEST_WAIT_MS
|
|
20
|
+
): Promise<void> {
|
|
8
21
|
const [sub, ...rest] = args
|
|
9
22
|
if (!sub || isHelp(sub) || requestsHelp(rest)) return writeText(GROUP_HELP.actions)
|
|
10
23
|
if (sub === "get") {
|
|
@@ -28,7 +41,6 @@ export async function actions(api: ApiClient, args: readonly string[]): Promise<
|
|
|
28
41
|
"--subject-id": "string",
|
|
29
42
|
"--file": "string",
|
|
30
43
|
"--run-id": "string",
|
|
31
|
-
"--wait": "boolean",
|
|
32
44
|
},
|
|
33
45
|
"actions request",
|
|
34
46
|
1
|
|
@@ -38,7 +50,6 @@ export async function actions(api: ApiClient, args: readonly string[]): Promise<
|
|
|
38
50
|
const subjectId = options["--subject-id"]
|
|
39
51
|
const paramsSource = options["--file"]
|
|
40
52
|
const runId = options["--run-id"]
|
|
41
|
-
const wait = options["--wait"]
|
|
42
53
|
if (Boolean(subjectType) !== Boolean(subjectId)) {
|
|
43
54
|
fail("--subject-type and --subject-id must be provided together.")
|
|
44
55
|
}
|
|
@@ -46,49 +57,40 @@ export async function actions(api: ApiClient, args: readonly string[]): Promise<
|
|
|
46
57
|
if (Array.isArray(params) || typeof params !== "object" || params === null) {
|
|
47
58
|
fail("Action params must be a JSON object.")
|
|
48
59
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
// The API answers once the Action has run, with its terminal run. Every request names its run,
|
|
61
|
+
// so that one this command stops waiting for can still be read: the run is not cancelled.
|
|
62
|
+
const requestedRunId = runId ?? `act_${randomUUID()}`
|
|
63
|
+
const waiting = AbortSignal.timeout(requestWaitMs)
|
|
64
|
+
try {
|
|
65
|
+
return writeRequestResult(
|
|
66
|
+
await api.post(
|
|
67
|
+
`/api/actions/${encodeURIComponent(actionId)}`,
|
|
68
|
+
{
|
|
69
|
+
params,
|
|
70
|
+
...(subjectType && subjectId
|
|
71
|
+
? { subject: { kind: "object", objectTypeId: subjectType, primaryId: subjectId } }
|
|
72
|
+
: {}),
|
|
73
|
+
runId: requestedRunId,
|
|
74
|
+
},
|
|
75
|
+
{ signal: waiting }
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
} catch (error) {
|
|
79
|
+
if (!waiting.aborted) throw error
|
|
60
80
|
throw new CliError(
|
|
61
81
|
{
|
|
62
|
-
code: "
|
|
63
|
-
message:
|
|
82
|
+
code: "action_wait_timeout",
|
|
83
|
+
message:
|
|
84
|
+
`Action run '${requestedRunId}' did not finish within ${requestWaitMs / 1_000} ` +
|
|
85
|
+
"seconds. It was not cancelled.",
|
|
86
|
+
hint:
|
|
87
|
+
`Read it with 'sixb action-runs get ${requestedRunId}': its record exists once it ` +
|
|
88
|
+
`has ended. A repeated request must pass '--run-id ${requestedRunId}', or the ` +
|
|
89
|
+
"Action runs twice.",
|
|
64
90
|
},
|
|
65
91
|
EXIT_API
|
|
66
92
|
)
|
|
67
93
|
}
|
|
68
|
-
return writeJson(await waitForActionRun(api, requestedRunId))
|
|
69
94
|
}
|
|
70
95
|
fail(`Unknown actions command '${sub}'.`)
|
|
71
96
|
}
|
|
72
|
-
|
|
73
|
-
const ACTION_WAIT_TIMEOUT_MS = 25_000
|
|
74
|
-
const ACTION_WAIT_POLL_MS = 250
|
|
75
|
-
const TERMINAL_ACTION_STATUSES = new Set(["succeeded", "failed", "cancelled"])
|
|
76
|
-
|
|
77
|
-
async function waitForActionRun(api: ApiClient, runId: string): Promise<unknown> {
|
|
78
|
-
const startedAt = Date.now()
|
|
79
|
-
while (Date.now() - startedAt < ACTION_WAIT_TIMEOUT_MS) {
|
|
80
|
-
const run = await api.get(`/api/action-runs/${encodeURIComponent(runId)}`)
|
|
81
|
-
const status = asRecord(run).status
|
|
82
|
-
if (typeof status === "string" && TERMINAL_ACTION_STATUSES.has(status)) return run
|
|
83
|
-
await new Promise((resolve) => setTimeout(resolve, ACTION_WAIT_POLL_MS))
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
throw new CliError(
|
|
87
|
-
{
|
|
88
|
-
code: "action_wait_timeout",
|
|
89
|
-
message: `Action run '${runId}' did not finish within ${ACTION_WAIT_TIMEOUT_MS / 1_000} seconds.`,
|
|
90
|
-
hint: `Inspect it with 'sixb action-runs get ${runId}'.`,
|
|
91
|
-
},
|
|
92
|
-
EXIT_API
|
|
93
|
-
)
|
|
94
|
-
}
|
package/src/commands/index.ts
CHANGED
|
@@ -2,11 +2,13 @@ import type { ApiClient } from "../api-client"
|
|
|
2
2
|
import { fail } from "../output"
|
|
3
3
|
import { actions } from "./actions"
|
|
4
4
|
import { files } from "./files"
|
|
5
|
+
import { models } from "./models"
|
|
5
6
|
import { objects } from "./objects"
|
|
6
7
|
import { ontology } from "./ontology"
|
|
7
8
|
import { project } from "./project"
|
|
8
9
|
import { runs } from "./runs"
|
|
9
10
|
import { telemetry } from "./telemetry"
|
|
11
|
+
import { users } from "./users"
|
|
10
12
|
import { workflows } from "./workflows"
|
|
11
13
|
|
|
12
14
|
export const INSTANCE_COMMANDS = [
|
|
@@ -19,6 +21,8 @@ export const INSTANCE_COMMANDS = [
|
|
|
19
21
|
"files",
|
|
20
22
|
"workflows",
|
|
21
23
|
"workflow-runs",
|
|
24
|
+
"users",
|
|
25
|
+
"models",
|
|
22
26
|
] as const
|
|
23
27
|
|
|
24
28
|
export type InstanceCommand = (typeof INSTANCE_COMMANDS)[number]
|
|
@@ -51,6 +55,10 @@ export async function dispatch(
|
|
|
51
55
|
return workflows(api, args)
|
|
52
56
|
case "workflow-runs":
|
|
53
57
|
return runs(api, "workflow", args)
|
|
58
|
+
case "users":
|
|
59
|
+
return users(api, args)
|
|
60
|
+
case "models":
|
|
61
|
+
return models(api, args)
|
|
54
62
|
default:
|
|
55
63
|
fail(`Unknown command '${command}'. Run 'sixb --help'.`)
|
|
56
64
|
}
|
package/src/commands/metadata.ts
CHANGED
|
@@ -28,6 +28,8 @@ Objects:
|
|
|
28
28
|
sixb objects inspect <type> <id> Inspect an object and its related graph in one command
|
|
29
29
|
sixb objects list [options] Browse materialized objects
|
|
30
30
|
sixb objects get <type> <id>... Exact lookup through opaque object references
|
|
31
|
+
sixb objects get-by <type> <property> <value>
|
|
32
|
+
The object holding a value of a unique property
|
|
31
33
|
sixb objects search <text> Search visible objects by id prefix and full text
|
|
32
34
|
sixb objects search <text> --type <type>
|
|
33
35
|
Semantic search through the type's vector profile
|
|
@@ -51,6 +53,13 @@ Actions and workflows:
|
|
|
51
53
|
Files:
|
|
52
54
|
sixb files upload|download ...
|
|
53
55
|
|
|
56
|
+
Members:
|
|
57
|
+
sixb users search <text> Find members by name or email
|
|
58
|
+
sixb users list|get ...
|
|
59
|
+
|
|
60
|
+
A user parameter or property is {"type":"user","id":"<user-id>"}. Find the id with
|
|
61
|
+
\`sixb users search <name>\`.
|
|
62
|
+
|
|
54
63
|
Run \`sixb <group> --help\` or \`sixb <group> <command> --help\` for exact arguments.
|
|
55
64
|
For query IR, run \`sixb objects query --help\` and \`sixb objects query --example list\`.`
|
|
56
65
|
|
|
@@ -68,6 +77,12 @@ const LOCAL_MAIN_HELP = SANDBOX_MAIN_HELP.replace("Sixb agent CLI", "Sixb instan
|
|
|
68
77
|
""
|
|
69
78
|
)
|
|
70
79
|
|
|
80
|
+
// The agent reaches models through its run's gateway once the model routes allow it.
|
|
81
|
+
.replace(
|
|
82
|
+
"Files:\n sixb files upload|download ...\n",
|
|
83
|
+
"Files:\n sixb files upload|download ...\n\nModels:\n sixb models list [--kind <kind>] Configured models of every kind, with prices\n sixb models get <model> One model's options and rate card\n sixb models text|image|speech|transcribe ... Call a model; see sixb models --help\n"
|
|
84
|
+
)
|
|
85
|
+
|
|
71
86
|
export function renderInstanceHelp(mode: "local" | "sandbox"): string {
|
|
72
87
|
return mode === "sandbox" ? SANDBOX_MAIN_HELP : LOCAL_MAIN_HELP
|
|
73
88
|
}
|
|
@@ -87,10 +102,19 @@ profiles.
|
|
|
87
102
|
|
|
88
103
|
${SEARCH_DETAILS}`
|
|
89
104
|
|
|
105
|
+
export const GET_BY_HELP = `Usage:
|
|
106
|
+
sixb objects get-by <object-type> <property> <value> [--json]
|
|
107
|
+
|
|
108
|
+
Prints the object of exactly <object-type> holding <value> for a property marked unique in its
|
|
109
|
+
ontology doc, or null when no visible object holds it. Values match exactly, case included.
|
|
110
|
+
The value is a string; with --json it is parsed as JSON, for an integer (42) or a user
|
|
111
|
+
reference ({"type":"user","id":"usr_1"}).`
|
|
112
|
+
|
|
90
113
|
export const OBJECTS_HELP = `Usage:
|
|
91
114
|
sixb objects inspect <object-type> <primary-id> [options]
|
|
92
115
|
sixb objects list [options]
|
|
93
116
|
sixb objects get <object-type> <primary-id>...
|
|
117
|
+
sixb objects get-by <object-type> <property> <value> [--json]
|
|
94
118
|
sixb objects search <text> [--type <object-type> [--vector-profile <name>]] [--limit <n>]
|
|
95
119
|
sixb objects query --file <path|-> [--include-total|--no-total]
|
|
96
120
|
sixb objects query --example <name>
|
|
@@ -158,7 +182,7 @@ Query nodes compose through input:
|
|
|
158
182
|
limit {"kind":"limit","input":<query>,"limit":${CLI_LIMITS.list.default}}
|
|
159
183
|
page {"kind":"page","input":<query>,"pageSize":${CLI_LIMITS.list.default},"pageToken":"from nextPageToken"}
|
|
160
184
|
project {"kind":"project","input":<query>,"properties":["name","status"]}
|
|
161
|
-
expand {"kind":"expand","input":<query>,"expansions":[{"linkId":"link","direction":"outgoing","limit":5}]}
|
|
185
|
+
expand {"kind":"expand","input":<query>,"expansions":[{"linkId":"link","direction":"outgoing","limit":5}],"users":["assignee"]}
|
|
162
186
|
vector {"kind":"vector","input":<start|filter>,"vector":"text","profile":"name","k":10}
|
|
163
187
|
rerank {"kind":"rerank","input":<vector>,"model":{"provider":"provider","modelId":"model"}}
|
|
164
188
|
|
|
@@ -169,11 +193,16 @@ Predicates use op, not kind:
|
|
|
169
193
|
{"op":"in","propertyId":"status","values":["open","blocked"]}
|
|
170
194
|
{"op":"exists","propertyId":"dueDate","value":true}
|
|
171
195
|
{"op":"contains","propertyId":"tags","value":"urgent"}
|
|
196
|
+
{"op":"eq","propertyId":"assignee","value":{"type":"currentUser"}} the caller, on a user reference: neq, in, contains too
|
|
172
197
|
|
|
173
198
|
Every field shown is required except includeSubtypes, fields, pageToken, properties, a sort
|
|
174
|
-
direction,
|
|
199
|
+
direction, an expansion's limit, and users. Sort by relevance after text or vector with
|
|
175
200
|
{"kind":"relevance"}. Wrap the outermost node in project to return only the properties you need.
|
|
176
201
|
|
|
202
|
+
An expand's users, or an expansion's, lists user-reference properties: each row then carries the
|
|
203
|
+
members' profiles under users (id, email, displayName, avatarUrl, status). Without access to the
|
|
204
|
+
member directory, users is empty.
|
|
205
|
+
|
|
177
206
|
Traversal and expansion directions are outgoing or incoming. For incoming relationships, the link
|
|
178
207
|
is declared on the child/source type; add sourceObjectTypeId when needed to disambiguate it.
|
|
179
208
|
|
|
@@ -204,11 +233,13 @@ History options:
|
|
|
204
233
|
actions: `Usage:
|
|
205
234
|
sixb actions list [--type <object-type>]
|
|
206
235
|
sixb actions get <action-id>
|
|
207
|
-
sixb actions request <action-id> [--subject-type <type> --subject-id <id>] [--file <path|->] [--run-id <id>]
|
|
236
|
+
sixb actions request <action-id> [--subject-type <type> --subject-id <id>] [--file <path|->] [--run-id <id>]
|
|
208
237
|
|
|
209
238
|
\`actions get\` includes inputSchema, the exact JSON shape accepted by the Action. The JSON file
|
|
210
|
-
contains that parameter object; use - to read standard input.
|
|
211
|
-
run and waits at most 25 seconds
|
|
239
|
+
contains that parameter object; use - to read standard input. \`actions request\` runs the Action
|
|
240
|
+
and prints its finished run, with its status and any error. It waits at most 25 seconds: a run that
|
|
241
|
+
takes longer keeps running, and the error names the run to read with \`action-runs get\`. A request
|
|
242
|
+
that waits for the user's approval prints \`"status": "awaiting_approval"\` and exits with code 4.`,
|
|
212
243
|
"action-runs": `Usage:
|
|
213
244
|
sixb action-runs list [options]
|
|
214
245
|
sixb action-runs get <run-id>
|
|
@@ -217,7 +248,7 @@ List options:
|
|
|
217
248
|
--action <action-id>
|
|
218
249
|
--type <object-type>
|
|
219
250
|
--id <primary-id>
|
|
220
|
-
--status
|
|
251
|
+
--status succeeded|failed
|
|
221
252
|
--started-after|--started-before <RFC3339>
|
|
222
253
|
--limit <1-${CLI_LIMITS.list.maximum}> Defaults to ${CLI_LIMITS.list.default}
|
|
223
254
|
--offset <n> Non-negative; defaults to 0
|
|
@@ -229,9 +260,48 @@ List options:
|
|
|
229
260
|
workflows: `Usage:
|
|
230
261
|
sixb workflows list
|
|
231
262
|
sixb workflows get <workflow-id>
|
|
232
|
-
sixb workflows start <workflow-id> [--file <path|->]
|
|
263
|
+
sixb workflows start <workflow-id> [--file <path|->] [--run-id <id>]
|
|
264
|
+
|
|
265
|
+
The JSON file contains the workflow input object. Use - to read standard input. A start that waits
|
|
266
|
+
for the user's approval prints \`"status": "awaiting_approval"\` and exits with code 4.`,
|
|
267
|
+
users: `Usage:
|
|
268
|
+
sixb users list [options]
|
|
269
|
+
sixb users search <text> [options]
|
|
270
|
+
sixb users get <user-id>
|
|
271
|
+
|
|
272
|
+
Options:
|
|
273
|
+
--status active|suspended|all Defaults to active
|
|
274
|
+
--limit <1-${CLI_LIMITS.users.maximum}> Defaults to ${CLI_LIMITS.users.default}
|
|
275
|
+
--offset <n> Non-negative; defaults to 0
|
|
233
276
|
|
|
234
|
-
|
|
277
|
+
\`users search\` matches part of a display name or email, ignoring case. Each member is
|
|
278
|
+
{"id","email","displayName","avatarUrl","status"}; a user parameter takes
|
|
279
|
+
{"type":"user","id":"<id>"}. Reading members requires can.view(project.users).`,
|
|
280
|
+
models: `Usage:
|
|
281
|
+
sixb models list [--kind language|image|speech|transcription]
|
|
282
|
+
sixb models get <model> [--kind <kind>]
|
|
283
|
+
sixb models text "<prompt>"|--file <path|-> [--model <tier|model>] [--instructions <text>]
|
|
284
|
+
[--max-output-tokens <n>] [--reasoning <level>]
|
|
285
|
+
sixb models image "<prompt>" --output <path> [--model <model>] [--n <n>]
|
|
286
|
+
[--size <size>] [--aspect-ratio <ratio>] [--quality <q>] [--style <s>]
|
|
287
|
+
[--seed <n>] [--image <file>]...
|
|
288
|
+
sixb models speech "<text>" --output <path> [--model <model>] [--voice <voice>]
|
|
289
|
+
[--format mp3|wav|ogg|aac|flac] [--instructions <text>]
|
|
290
|
+
[--speed <n>] [--language <code>]
|
|
291
|
+
sixb models transcribe <file> [--model <model>]
|
|
292
|
+
sixb models calls files <call-id> [--output <path>]
|
|
293
|
+
|
|
294
|
+
<model> is a model id, or provider:model-id when two providers share one; without --model, the
|
|
295
|
+
kind's default answers. \`list\` shows each model's kind, default, description and price; \`get\`
|
|
296
|
+
adds the sizes, voices and other options a request can use. Prices are in USD.
|
|
297
|
+
|
|
298
|
+
\`text\` also takes a tier (light, standard or heavy) for --model, and reads a long prompt from
|
|
299
|
+
--file: a path, or - for standard input.
|
|
300
|
+
|
|
301
|
+
--output is a file, numbered when a call returns several, or a directory ending in /. The
|
|
302
|
+
extension follows the file's type, and the result lists the paths written. --image uploads a
|
|
303
|
+
reference image; repeat it for several. \`calls files\` lists a past call's files, or downloads
|
|
304
|
+
them again.`,
|
|
235
305
|
"workflow-runs": `Usage:
|
|
236
306
|
sixb workflow-runs list [options]
|
|
237
307
|
sixb workflow-runs get <run-id>
|
|
@@ -253,10 +323,12 @@ export const QUERY_EXAMPLES: Readonly<Record<string, string>> = {
|
|
|
253
323
|
not: `{"kind":"limit","input":{"kind":"filter","input":{"kind":"start","objectTypeId":"Customer"},"predicate":{"op":"not","item":{"op":"eq","propertyId":"status","value":"churned"}}},"limit":${CLI_LIMITS.list.default}}`,
|
|
254
324
|
in: `{"kind":"limit","input":{"kind":"filter","input":{"kind":"start","objectTypeId":"Customer"},"predicate":{"op":"in","propertyId":"status","values":["active","trial"]}},"limit":${CLI_LIMITS.list.default}}`,
|
|
255
325
|
exists: `{"kind":"limit","input":{"kind":"filter","input":{"kind":"start","objectTypeId":"Customer"},"predicate":{"op":"exists","propertyId":"accountManager","value":false}},"limit":${CLI_LIMITS.list.default}}`,
|
|
326
|
+
mine: `{"kind":"limit","input":{"kind":"filter","input":{"kind":"start","objectTypeId":"Task"},"predicate":{"op":"eq","propertyId":"assignee","value":{"type":"currentUser"}}},"limit":${CLI_LIMITS.list.default}}`,
|
|
256
327
|
project: `{"kind":"project","input":{"kind":"limit","input":{"kind":"start","objectTypeId":"Customer"},"limit":${CLI_LIMITS.list.default}},"properties":["name","status"]}`,
|
|
257
328
|
incoming:
|
|
258
329
|
'{"kind":"traverse","input":{"kind":"refs","refs":[{"objectTypeId":"RepositoryIssue","primaryId":"github:issue:owner/repo#297"}]},"linkId":"issue","direction":"incoming","sourceObjectTypeId":"RepositoryComment"}',
|
|
259
330
|
expand: `{"kind":"expand","input":{"kind":"refs","refs":[{"objectTypeId":"RepositoryIssue","primaryId":"github:issue:owner/repo#297"}]},"expansions":[{"linkId":"issue","direction":"incoming","sourceObjectTypeId":"RepositoryComment","limit":${CLI_LIMITS.list.default}}]}`,
|
|
331
|
+
users: `{"kind":"expand","input":{"kind":"limit","input":{"kind":"start","objectTypeId":"Task"},"limit":${CLI_LIMITS.list.default}},"expansions":[],"users":["assignee"]}`,
|
|
260
332
|
sort: `{"kind":"limit","input":{"kind":"sort","input":{"kind":"start","objectTypeId":"Customer"},"fields":[{"kind":"property","propertyId":"name","direction":"asc"}]},"limit":${CLI_LIMITS.list.default}}`,
|
|
261
333
|
page: `{"kind":"page","input":{"kind":"start","objectTypeId":"Customer"},"pageSize":${CLI_LIMITS.list.default}}`,
|
|
262
334
|
vector: `{"kind":"vector","input":{"kind":"filter","input":{"kind":"start","objectTypeId":"Product"},"predicate":{"op":"eq","propertyId":"status","value":"active"}},"vector":"waterproof trail shoes","profile":"content","k":${CLI_LIMITS.search.default}}`,
|