@tonbo/cli 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,7 +44,7 @@ Use the arrow keys and Enter to select a supported Harness and either create or
44
44
  The generated `.tonbo` is TOML:
45
45
 
46
46
  ```toml
47
- # Tonbo Agent Agent configuration.
47
+ # Tonbo Agent configuration.
48
48
  # Edit this file directly or run `tonbo init` to reconfigure.
49
49
  version = 2
50
50
  agent = "my-agent-my-account.tonbo.sh"
@@ -61,7 +61,7 @@ model = "claude-sonnet-4-5"
61
61
 
62
62
  The immutable full Agent hostname is the only durable Agent authority in the source tree; it is not a credential. This keeps Agents with the same name in different Organizations unambiguous. `deploy`, `run`, `ssh` and `secret` refuse an unbound declaration. `tonbo agent use <name-hostname-or-id>` accepts any convenient selector, resolves it through the signed-in account and writes the selected `project-organization.tonbo.sh` hostname into `.tonbo`; rebinding an existing declaration requires interactive confirmation or `--force`. UUIDs remain internal API identities and are never committed by the CLI.
63
63
 
64
- The default inference model is written without prompting. Override it explicitly with `--model`. Headless initialization makes Harness and driver choices explicit and may bind the resulting declaration with `project use`:
64
+ The default inference model is written without prompting. Override it explicitly with `--model`. Headless initialization makes Harness and driver choices explicit and may bind the resulting declaration with `agent use`:
65
65
 
66
66
  ```console
67
67
  tonbo init --harness pi --driver native
@@ -200,3 +200,21 @@ Node.js 22 or newer is required. Human OAuth tokens are stored at `${XDG_CONFIG_
200
200
  - [Agent Deployments, Production and Rollouts](../../docs/design/project-deployments.md)
201
201
  - [ADR-0008: Tonbo CLI onboarding and credential boundaries](../../apps/user-center/docs/decisions/adr-0008-tonbo-cli-onboarding.md)
202
202
  - [Management API v1](../../contracts/management/openapi-v1.yaml)
203
+
204
+ ## Machines
205
+
206
+ Machines belong to an Account independently of Agents. Allocate in `us-east-1`, bind an available Machine from Agent detail or the CLI, inspect measured metrics, and release it when no longer needed. Allocation starts no compute. The platform handles idle pause/resume automatically; there are no customer power controls or arbitrary Machine command/upload APIs.
207
+
208
+ ```console
209
+ tonbo --json machine allocate --account <account-uuid> --region us-east-1
210
+ tonbo --json machine list --account <account-uuid>
211
+ tonbo --json machine bind <machine-uuid> --agent <agent-uuid>
212
+ tonbo --json machine show <machine-uuid>
213
+ tonbo --json machine metrics <machine-uuid>
214
+ tonbo --json machine unbind <machine-uuid>
215
+ tonbo --json machine release <machine-uuid>
216
+ ```
217
+
218
+ Only one active Agent binding per Machine and one Machine per Agent are currently supported. Unbinding drains execution and completes physical deletion, final usage settlement and storage credential revocation before the Machine becomes available. Wait for `available: true` in `machine show` before rebinding. Cross-Agent reassignment resets rootfs; the destination mounts its own Agent Workspace and Sessions. Hidden pause/resume within the same Agent retains rootfs and process state. Release also drains an existing binding automatically; it does not delete Agent files or Sessions.
219
+
220
+ `tonbo agent list` lists accessible Agents without requiring a local `.tonbo` file. JSON command output uses `agent` for one Agent and `agents` for the list; there is no duplicate `project` output alias.
package/dist/bin/tonbo.js CHANGED
@@ -1734,7 +1734,7 @@ function initSaveLabel(exists, project) {
1734
1734
  }
1735
1735
  async function selectInitProject(deps, root) {
1736
1736
  for (; ; ) {
1737
- const action = await deps.select("How should this Agent connect to Tonbo?", [
1737
+ const action = await deps.select("How should this directory connect to Tonbo?", [
1738
1738
  {
1739
1739
  description: "Create it only after you confirm the complete configuration.",
1740
1740
  name: "Create a new agent",
@@ -1782,7 +1782,7 @@ async function selectInitProject(deps, root) {
1782
1782
  continue;
1783
1783
  }
1784
1784
  const id = await deps.select(
1785
- "Which agent should this Agent use?",
1785
+ "Which agent should this directory use?",
1786
1786
  projects.map((project2) => ({
1787
1787
  name: project2.name,
1788
1788
  description: `Organization: ${project2.organizationName} \xB7 ${project2.publicHostname} \xB7 ${project2.id}`,
@@ -1935,7 +1935,10 @@ async function projectUseCommand(deps, selector, force = false) {
1935
1935
  const projects = await deps.api.listProjects(oauthToken);
1936
1936
  const project = selectProject(projects, selector);
1937
1937
  if (declaration.agent === project.publicHostname) {
1938
- deps.output({ message: `.tonbo already uses agent ${project.publicHostname}.`, project });
1938
+ deps.output({
1939
+ message: `.tonbo already uses agent ${project.publicHostname}.`,
1940
+ agent: project
1941
+ });
1939
1942
  return;
1940
1943
  }
1941
1944
  if (declaration.agent && !force) {
@@ -1959,7 +1962,7 @@ async function projectUseCommand(deps, selector, force = false) {
1959
1962
  }
1960
1963
  }
1961
1964
  await bindDeclarationProject(root, project.publicHostname);
1962
- deps.output({ message: `Bound .tonbo to agent ${project.publicHostname}.`, project });
1965
+ deps.output({ message: `Bound .tonbo to agent ${project.publicHostname}.`, agent: project });
1963
1966
  }
1964
1967
  async function projectCreateCommand(deps, name) {
1965
1968
  const root = await findDeclarationRoot(deps.cwd());
@@ -1980,7 +1983,7 @@ async function projectCreateCommand(deps, name) {
1980
1983
  { cause: error }
1981
1984
  );
1982
1985
  }
1983
- deps.output({ message: `Created agent ${project.name} and bound it in .tonbo.`, project });
1986
+ deps.output({ message: `Created agent ${project.name} and bound it in .tonbo.`, agent: project });
1984
1987
  }
1985
1988
  async function deployCommand(deps, options = { promote: true }) {
1986
1989
  const { declaration, oauthToken, project, root } = await resolveProject(deps);
@@ -2023,7 +2026,7 @@ async function deployCommand(deps, options = { promote: true }) {
2023
2026
  ` ssh ${project.sshDestination}`
2024
2027
  );
2025
2028
  }
2026
- deps.output({ message: lines.join("\n"), project, ...result });
2029
+ deps.output({ message: lines.join("\n"), agent: project, ...result });
2027
2030
  }
2028
2031
  async function runCommand(deps, prompt, options) {
2029
2032
  const { oauthToken, project } = await resolveProject(deps);
@@ -2036,10 +2039,17 @@ async function runCommand(deps, prompt, options) {
2036
2039
  });
2037
2040
  deps.output({
2038
2041
  message: result.turn.assistant_text,
2039
- project,
2042
+ agent: project,
2040
2043
  ...result
2041
2044
  });
2042
2045
  }
2046
+ async function agentListCommand(deps) {
2047
+ const agents = await deps.api.listProjects(await deps.auth.accessToken());
2048
+ deps.output({
2049
+ message: agents.length ? agents.map((agent) => `${agent.name} \xB7 ${agent.publicHostname}`).join("\n") : "No agents are available.",
2050
+ agents
2051
+ });
2052
+ }
2043
2053
  async function projectShowCommand(deps) {
2044
2054
  const { project, token } = await projectManagement(deps);
2045
2055
  const production = await deps.api.getProduction(project.id, token);
@@ -2055,7 +2065,7 @@ async function projectShowCommand(deps) {
2055
2065
  `production: ${deploymentName(deployment)} (${shortDeploymentId(deployment.id)}) ${productionStateLabel(deployment)}`
2056
2066
  );
2057
2067
  }
2058
- deps.output({ message: lines.join("\n"), project, production, deployment });
2068
+ deps.output({ message: lines.join("\n"), agent: project, production, deployment });
2059
2069
  }
2060
2070
  function shortDeploymentId(id) {
2061
2071
  return id.replace(/-/g, "").slice(0, 8);
@@ -2125,7 +2135,7 @@ async function deploymentsListCommand(deps) {
2125
2135
  deployment.created_by_user_id ? shortDeploymentId(deployment.created_by_user_id) : ""
2126
2136
  ])
2127
2137
  ) : `No Deployments exist for agent ${project.name}. Run \`tonbo deploy\` to create one.`;
2128
- deps.output({ message, project, production, deployments });
2138
+ deps.output({ message, agent: project, production, deployments });
2129
2139
  }
2130
2140
  async function deploymentsShowCommand(deps, prefix) {
2131
2141
  const { project, token } = await projectManagement(deps);
@@ -2135,7 +2145,7 @@ async function deploymentsShowCommand(deps, prefix) {
2135
2145
  );
2136
2146
  deps.output({
2137
2147
  message: renderDeploymentDetail(deployment, rollouts),
2138
- project,
2148
+ agent: project,
2139
2149
  deployment,
2140
2150
  rollouts
2141
2151
  });
@@ -2181,7 +2191,7 @@ async function deploymentsPromoteCommand(deps, prefix) {
2181
2191
  const result = await moveProduction(deps, project.id, target, token);
2182
2192
  deps.output({
2183
2193
  message: describeProductionMove(project, result, "Promoted"),
2184
- project,
2194
+ agent: project,
2185
2195
  ...result
2186
2196
  });
2187
2197
  }
@@ -2205,7 +2215,7 @@ async function deploymentsRollbackCommand(deps, prefix) {
2205
2215
  const result = await moveProduction(deps, project.id, target, token);
2206
2216
  deps.output({
2207
2217
  message: describeProductionMove(project, result, "Rolled back"),
2208
- project,
2218
+ agent: project,
2209
2219
  ...result
2210
2220
  });
2211
2221
  }
@@ -2246,7 +2256,7 @@ async function secretListCommand(deps) {
2246
2256
  const secrets = await deps.api.listProjectSecrets(project.id, token);
2247
2257
  deps.output({
2248
2258
  message: secrets.length ? secrets.map((secret) => secret.name).join("\n") : "No agent secrets are configured.",
2249
- project,
2259
+ agent: project,
2250
2260
  secrets
2251
2261
  });
2252
2262
  }
@@ -2256,14 +2266,14 @@ async function secretSetCommand(deps, name, options) {
2256
2266
  const secret = await deps.api.setProjectSecret(project.id, name, value, token);
2257
2267
  deps.output({
2258
2268
  message: `Set agent secret ${secret.name}. Redeploy to replace the active runtime with this value.`,
2259
- project,
2269
+ agent: project,
2260
2270
  secret
2261
2271
  });
2262
2272
  }
2263
2273
  async function secretRemoveCommand(deps, name) {
2264
2274
  const { project, token } = await projectManagement(deps);
2265
2275
  await deps.api.deleteProjectSecret(project.id, name, token);
2266
- deps.output({ message: `Removed agent secret ${name}.`, project, name });
2276
+ deps.output({ message: `Removed agent secret ${name}.`, agent: project, name });
2267
2277
  }
2268
2278
 
2269
2279
  // src/credentials.ts
@@ -2523,7 +2533,7 @@ function jsonOutput(program) {
2523
2533
  return program.opts().json === true;
2524
2534
  }
2525
2535
  function createProgram(dependencies = createDependencies) {
2526
- const program = new Command().name("tonbo").description("Deploy a persistent Agent Agent to Tonbo.").version(packageVersion.version).option("--json", "print machine-readable JSON");
2536
+ const program = new Command().name("tonbo").description("Deploy a persistent Agent to Tonbo.").version(packageVersion.version).option("--json", "print machine-readable JSON");
2527
2537
  program.command("init").description("interactively create a Tonbo Agent declaration in this directory").option("--harness <harness>", "Agent Harness (currently pi)").option("--model <model>", "inference model").option("--driver <driver>", "PI driver: native or command").option("--agent-entry <file>", "Node entry file for the command driver").option("--build-command <argv...>", "build command argv for the command driver").option("--force", `replace an existing ${DECLARATION_FILENAME}`).action(
2528
2538
  async (options) => initCommand(dependencies(jsonOutput(program)), options)
2529
2539
  );
@@ -2583,17 +2593,18 @@ function createProgram(dependencies = createDependencies) {
2583
2593
  })
2584
2594
  );
2585
2595
  });
2586
- const project = program.command("agent").description("manage the agent bound to this Agent directory");
2587
- project.command("create <name>").description("create and bind a agent to this Agent directory").action(async (name) => projectCreateCommand(dependencies(jsonOutput(program)), name));
2596
+ const project = program.command("agent").description("manage the Agent bound to this source directory");
2597
+ project.command("create <name>").description("create an agent and bind this directory to it").action(async (name) => projectCreateCommand(dependencies(jsonOutput(program)), name));
2598
+ project.command("list").description("list the agents available to your account").action(async () => agentListCommand(dependencies(jsonOutput(program))));
2588
2599
  const sshKey = program.command("ssh-key").description("manage public keys used by native agent SSH");
2589
2600
  sshKey.command("add <public-key>").description("register an OpenSSH public key with the current Tonbo account").action(async (path6) => sshKeyAddCommand(dependencies(jsonOutput(program)), path6));
2590
2601
  sshKey.command("remove <fingerprint>").description("revoke an SSH public key from the current Tonbo account").action(
2591
2602
  async (fingerprint) => sshKeyRemoveCommand(dependencies(jsonOutput(program)), fingerprint)
2592
2603
  );
2593
- project.command("use <agent>").description("write a agent ID into this Agent's .tonbo declaration").option("--force", "replace an existing agent binding without confirmation").action(
2604
+ project.command("use <agent>").description("write the agent hostname into this directory's .tonbo declaration").option("--force", "replace an existing agent binding without confirmation").action(
2594
2605
  async (selector, options) => projectUseCommand(dependencies(jsonOutput(program)), selector, options.force === true)
2595
2606
  );
2596
- project.command("show").description("show the agent bound to this Agent directory and its connection addresses").action(async () => projectShowCommand(dependencies(jsonOutput(program))));
2607
+ project.command("show").description("show the agent bound to this directory and its connection addresses").action(async () => projectShowCommand(dependencies(jsonOutput(program))));
2597
2608
  program.command("deploy").description("upload this directory as a new Deployment and promote it to Production").option("--no-promote", "create the Deployment without moving Production").action(
2598
2609
  async (options) => deployCommand(dependencies(jsonOutput(program)), { promote: options.promote })
2599
2610
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonbo/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Deploy persistent Agents and manage their Machines from the command line.",
5
5
  "homepage": "https://tonbo.dev",
6
6
  "bugs": {