@sixb/cli-core 0.1.9 → 0.1.10

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 (59) hide show
  1. package/README.md +21 -16
  2. package/dist/api-client.d.ts +1 -0
  3. package/dist/api-client.d.ts.map +1 -1
  4. package/dist/bin/sixb +26 -0
  5. package/dist/commands/data.d.ts +5 -0
  6. package/dist/commands/data.d.ts.map +1 -0
  7. package/dist/commands/files.d.ts.map +1 -1
  8. package/dist/commands/index.d.ts +1 -1
  9. package/dist/commands/index.d.ts.map +1 -1
  10. package/dist/commands/memory.d.ts +3 -0
  11. package/dist/commands/memory.d.ts.map +1 -0
  12. package/dist/commands/metadata.d.ts +10 -4
  13. package/dist/commands/metadata.d.ts.map +1 -1
  14. package/dist/commands/runs.d.ts +8 -1
  15. package/dist/commands/runs.d.ts.map +1 -1
  16. package/dist/commands/shared.d.ts +2 -0
  17. package/dist/commands/shared.d.ts.map +1 -1
  18. package/dist/commands/system.d.ts +21 -0
  19. package/dist/commands/system.d.ts.map +1 -0
  20. package/dist/commands/users.d.ts.map +1 -1
  21. package/dist/generated/sixb.mjs +2547 -0
  22. package/dist/index.d.ts +8 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +290 -58
  25. package/dist/index.js.map +21 -17
  26. package/dist/main.d.ts +3 -0
  27. package/dist/main.d.ts.map +1 -0
  28. package/dist/memory.d.ts +21 -0
  29. package/dist/memory.d.ts.map +1 -0
  30. package/dist/policies.d.ts +9 -0
  31. package/dist/policies.d.ts.map +1 -1
  32. package/dist/run.d.ts +1 -0
  33. package/dist/run.d.ts.map +1 -1
  34. package/dist/sandbox-cli.d.ts +8 -0
  35. package/dist/sandbox-cli.d.ts.map +1 -0
  36. package/package.json +15 -1
  37. package/src/api-client.ts +70 -2
  38. package/src/bin/sixb +26 -0
  39. package/src/commands/actions.ts +3 -3
  40. package/src/commands/data.ts +90 -0
  41. package/src/commands/files.ts +27 -3
  42. package/src/commands/index.ts +16 -0
  43. package/src/commands/memory.ts +358 -0
  44. package/src/commands/metadata.ts +69 -29
  45. package/src/commands/models.ts +3 -3
  46. package/src/commands/ontology.ts +2 -2
  47. package/src/commands/runs.ts +22 -16
  48. package/src/commands/shared.ts +6 -0
  49. package/src/commands/system.ts +67 -0
  50. package/src/commands/telemetry.ts +2 -2
  51. package/src/commands/users.ts +22 -2
  52. package/src/commands/workflows.ts +3 -3
  53. package/src/generated/sixb.mjs +2547 -0
  54. package/src/index.ts +12 -3
  55. package/src/main.ts +39 -0
  56. package/src/memory.ts +30 -0
  57. package/src/policies.ts +3 -0
  58. package/src/run.ts +3 -2
  59. package/src/sandbox-cli.ts +18 -0
@@ -0,0 +1,67 @@
1
+ import { readFile } from "node:fs/promises"
2
+ import { isHelp } from "../arguments"
3
+ import { CliError, EXIT_API, fail, INSTANCE_CLI_VERSION, writeJson, writeText } from "../output"
4
+ import { createInstanceApiClient, type SandboxInstanceCliMode } from "../run"
5
+ import { asRecord, isFileError } from "./shared"
6
+
7
+ /** The sandbox runtime `sixb status` reports and the agent worker's preflight expects. */
8
+ export const AGENT_RUNTIME_PROFILE = "sixb-agent-runtime/v1" as const
9
+
10
+ /** Stable JSON emitted by `sixb status` in a sandbox and consumed by worker preflight. */
11
+ export interface SandboxStatusReport {
12
+ readonly ok: true
13
+ readonly profile: typeof AGENT_RUNTIME_PROFILE
14
+ readonly cli: { readonly version: string }
15
+ readonly javascript: {
16
+ readonly name: "bun" | "node"
17
+ readonly version: string
18
+ }
19
+ readonly project: { readonly id: string }
20
+ }
21
+
22
+ export async function status(args: readonly string[], mode: SandboxInstanceCliMode): Promise<void> {
23
+ if (isHelp(args[0])) return writeText("Usage: sixb status")
24
+ // Its output is JSON either way: --json, which people's `sixb status` takes, changes nothing.
25
+ if (args.some((arg) => arg !== "--json")) fail("status accepts no arguments but --json.")
26
+ const project = asRecord(await createInstanceApiClient(mode).get("/api/project"))
27
+ if (typeof project.id !== "string" || project.id.length === 0) {
28
+ throw new CliError(
29
+ { code: "invalid_api_response", message: "The Sixb API returned an invalid project." },
30
+ EXIT_API
31
+ )
32
+ }
33
+ const report: SandboxStatusReport = {
34
+ ok: true,
35
+ profile: AGENT_RUNTIME_PROFILE,
36
+ cli: { version: INSTANCE_CLI_VERSION },
37
+ javascript: javascriptRuntime(),
38
+ project: { id: project.id },
39
+ }
40
+ writeJson(report)
41
+ }
42
+
43
+ export async function context(args: readonly string[]): Promise<void> {
44
+ if (isHelp(args[0])) return writeText("Usage: sixb context")
45
+ if (args.length !== 0) fail("context accepts no arguments.")
46
+ const path = process.env.SIXB_RUN_CONTEXT
47
+ if (!path) fail("SIXB_RUN_CONTEXT is not set.")
48
+ let text: string
49
+ try {
50
+ text = await readFile(path, "utf8")
51
+ } catch (error) {
52
+ if (isFileError(error, "ENOENT")) fail(`Run context '${path}' does not exist.`)
53
+ throw error
54
+ }
55
+ try {
56
+ writeJson(JSON.parse(text))
57
+ } catch {
58
+ fail(`Run context '${path}' is not valid JSON.`, "invalid_json")
59
+ }
60
+ }
61
+
62
+ function javascriptRuntime(): SandboxStatusReport["javascript"] {
63
+ if (typeof globalThis.Bun === "object") {
64
+ return { name: "bun", version: globalThis.Bun.version }
65
+ }
66
+ return { name: "node", version: process.versions.node }
67
+ }
@@ -11,7 +11,7 @@ import {
11
11
  import { fail, writeJson, writeText } from "../output"
12
12
  import { CLI_LIMITS, DEFAULT_TELEMETRY_ORDER } from "../policies"
13
13
  import { GROUP_HELP } from "./metadata"
14
- import { normalizeWindowOptions, readJson, singleFileOption } from "./shared"
14
+ import { idSegment, normalizeWindowOptions, readJson, singleFileOption } from "./shared"
15
15
 
16
16
  export async function telemetry(api: ApiClient, args: readonly string[]): Promise<void> {
17
17
  const [sub, ...rest] = args
@@ -62,7 +62,7 @@ export async function telemetry(api: ApiClient, args: readonly string[]): Promis
62
62
  }
63
63
 
64
64
  function telemetryPath(args: readonly string[], terminal: "latest" | "history"): string {
65
- return `/api/objects/${encodeURIComponent(args[0] ?? "")}/${encodeURIComponent(args[1] ?? "")}/telemetry/${encodeURIComponent(args[2] ?? "")}/${terminal}`
65
+ return `/api/objects/${idSegment(args[0])}/${idSegment(args[1])}/telemetry/${idSegment(args[2])}/${terminal}`
66
66
  }
67
67
 
68
68
  function normalizeTelemetryQueryInput(input: unknown): Record<string, unknown> {
@@ -7,10 +7,11 @@ import {
7
7
  parseCommandArgs,
8
8
  requestsHelp,
9
9
  } from "../arguments"
10
- import { fail, writeJson, writeText } from "../output"
10
+ import { CliError, EXIT_API, fail, writeJson, writeText } from "../output"
11
11
  import { CLI_LIMITS } from "../policies"
12
12
  import { GROUP_HELP } from "./metadata"
13
13
  import type { QueryOptions } from "./shared"
14
+ import { idSegment } from "./shared"
14
15
 
15
16
  const USER_STATUSES = ["active", "suspended", "all"] as const
16
17
 
@@ -26,7 +27,22 @@ export async function users(api: ApiClient, args: readonly string[]): Promise<vo
26
27
 
27
28
  if (sub === "get") {
28
29
  const { positionals } = parseCommandArgs(rest, {}, "users get", 1)
29
- return writeJson(await api.get(`/api/users/${encodeURIComponent(positionals[0] ?? "")}`))
30
+ const user = positionals[0]?.trim()
31
+ if (!user) fail("users get requires a user id or email.")
32
+ // Sign-in mints ids as `usr_<uuid>`, so an `@` marks an email.
33
+ if (!user.includes("@")) {
34
+ return writeJson(await api.get(`/api/users/${idSegment(user)}`))
35
+ }
36
+
37
+ const page = await api.get("/api/users", { email: user })
38
+ const [member] = isRecord(page) && Array.isArray(page.users) ? page.users : []
39
+ if (member === undefined) {
40
+ throw new CliError(
41
+ { code: "not_found", message: `No member has the email '${user}'.` },
42
+ EXIT_API
43
+ )
44
+ }
45
+ return writeJson(member)
30
46
  }
31
47
 
32
48
  if (sub === "list") {
@@ -65,3 +81,7 @@ function listQuery(options: {
65
81
  : { offset: String(nonNegativeInteger("--offset", options["--offset"])) }),
66
82
  }
67
83
  }
84
+
85
+ function isRecord(value: unknown): value is Record<string, unknown> {
86
+ return typeof value === "object" && value !== null && !Array.isArray(value)
87
+ }
@@ -3,7 +3,7 @@ import type { ApiClient } from "../api-client"
3
3
  import { isHelp, parseCommandArgs, requestsHelp } from "../arguments"
4
4
  import { fail, writeJson, writeRequestResult, writeText } from "../output"
5
5
  import { GROUP_HELP } from "./metadata"
6
- import { readJson } from "./shared"
6
+ import { idSegment, readJson } from "./shared"
7
7
 
8
8
  export async function workflows(api: ApiClient, args: readonly string[]): Promise<void> {
9
9
  const [sub, ...rest] = args
@@ -16,7 +16,7 @@ export async function workflows(api: ApiClient, args: readonly string[]): Promis
16
16
  const {
17
17
  positionals: [workflowId],
18
18
  } = parseCommandArgs(rest, {}, "workflows get", 1)
19
- return writeJson(await api.get(`/api/workflows/${encodeURIComponent(workflowId ?? "")}`))
19
+ return writeJson(await api.get(`/api/workflows/${idSegment(workflowId)}`))
20
20
  }
21
21
  if (sub === "start") {
22
22
  const {
@@ -30,7 +30,7 @@ export async function workflows(api: ApiClient, args: readonly string[]): Promis
30
30
  // Every start names its run, so a repeated request returns the same run instead of another.
31
31
  const runId = options["--run-id"] ?? `run_${randomUUID()}`
32
32
  return writeRequestResult(
33
- await api.post(`/api/workflows/${encodeURIComponent(workflowId ?? "")}/runs`, {
33
+ await api.post(`/api/workflows/${idSegment(workflowId)}/runs`, {
34
34
  input,
35
35
  runId,
36
36
  })