@tonbo/cli 0.1.0 → 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 +36 -18
- package/dist/bin/tonbo.js +85 -74
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -17,12 +17,12 @@ No Harness-specific configuration was found in this project.
|
|
|
17
17
|
❯ PI (`pi`) Run this project with the pi command.
|
|
18
18
|
? How should this Agent connect to Tonbo?
|
|
19
19
|
❯ Create a new project Create it only after you confirm the complete configuration.
|
|
20
|
-
Use an existing
|
|
20
|
+
Use an existing agent
|
|
21
21
|
Set up later
|
|
22
|
-
?
|
|
22
|
+
? Agent name [my-agent]:
|
|
23
23
|
|
|
24
24
|
Tonbo Agent configuration:
|
|
25
|
-
|
|
25
|
+
Agent: Create my-agent in my-account (permanent address assigned after creation)
|
|
26
26
|
Harness: PI
|
|
27
27
|
Execution: PI CLI (`pi`)
|
|
28
28
|
Model: claude-sonnet-4-5
|
|
@@ -31,7 +31,7 @@ Tonbo Agent configuration:
|
|
|
31
31
|
Edit configuration Change the project, Harness, execution mode, model, or SDK entrypoint.
|
|
32
32
|
Cancel
|
|
33
33
|
Created project my-agent and .tonbo.
|
|
34
|
-
|
|
34
|
+
Agent: my-agent (my-agent-my-account.tonbo.sh)
|
|
35
35
|
Organization: my-account
|
|
36
36
|
Application: https://my-agent-my-account.tonbo.sh
|
|
37
37
|
Harness: PI
|
|
@@ -39,12 +39,12 @@ Mode: PI CLI
|
|
|
39
39
|
Next: tonbo deploy
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
Use the arrow keys and Enter to select a supported Harness and either create or select the one
|
|
42
|
+
Use the arrow keys and Enter to select a supported Harness and either create or select the one Agent owned by this source tree. Agent creation and file writes wait until the final review; cancelling leaves both local and cloud state unchanged. `AGENTS.md` is Harness-neutral and never identifies PI by itself. When `.pi/settings.json` exists, the shared source inspector identifies the PI Harness and reports its workspace-local packages. A regular PI project defaults to the native PI CLI; choose `Edit configuration` only when changing the Agent, execution mode, model, or another setting. Unsupported and planned Harnesses are not shown.
|
|
43
43
|
|
|
44
44
|
The generated `.tonbo` is TOML:
|
|
45
45
|
|
|
46
46
|
```toml
|
|
47
|
-
# Tonbo
|
|
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"
|
|
@@ -59,14 +59,14 @@ kind = "native"
|
|
|
59
59
|
model = "claude-sonnet-4-5"
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
The immutable full
|
|
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 `
|
|
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
|
|
68
68
|
tonbo init --harness pi --driver command --agent-entry dist/agent.mjs
|
|
69
|
-
tonbo
|
|
69
|
+
tonbo agent use my-project-my-account.tonbo.sh
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
After interactive initialization, deploy the current contents:
|
|
@@ -76,7 +76,7 @@ tonbo deploy
|
|
|
76
76
|
tonbo run "Reply with exactly READY."
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
Choose `Use an existing
|
|
79
|
+
Choose `Use an existing agent` during `init` when the Agent already exists. `tonbo agent create <name>` and `tonbo agent use <name-hostname-or-id>` remain explicit automation and recovery commands.
|
|
80
80
|
|
|
81
81
|
`run` creates a durable Session and prints its ID in `--json` output. Pass that identity back to continue the same PI conversation:
|
|
82
82
|
|
|
@@ -84,7 +84,7 @@ Choose `Use an existing project` during `init` when the Project already exists.
|
|
|
84
84
|
tonbo run --session 4d8e9501-... "Continue the previous task."
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
Every `tonbo deploy` creates one immutable Deployment: the uploaded source, the `.tonbo` settings and the git provenance of the source root (commit, branch, subject, author and whether the tree was dirty) when the directory is inside a git work tree. Git is optional; without it the Deployment records `tonbo deploy` as its source. Deployments are named by their commit subject, or by their short id (the first eight hex characters) when there is no commit, and every command that takes a Deployment accepts any unambiguous id prefix. The
|
|
87
|
+
Every `tonbo deploy` creates one immutable Deployment: the uploaded source, the `.tonbo` settings and the git provenance of the source root (commit, branch, subject, author and whether the tree was dirty) when the directory is inside a git work tree. Git is optional; without it the Deployment records `tonbo deploy` as its source. Deployments are named by their commit subject, or by their short id (the first eight hex characters) when there is no commit, and every command that takes a Deployment accepts any unambiguous id prefix. The Agent's Production pointer names the one Deployment that serves its hostname; `deploy` moves Production to the new Deployment and prints the Deployment, its Production state and the exact standard OpenSSH command for the bound Agent and its username:
|
|
88
88
|
|
|
89
89
|
```console
|
|
90
90
|
$ tonbo deploy
|
|
@@ -115,15 +115,15 @@ tonbo deployments rollback # move Production back to the previous Pr
|
|
|
115
115
|
tonbo deployments rollback 9b8c1d22 # or to a named one
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
-
`tonbo deployments` (alias `tonbo deployments list`) marks the current Production Deployment with `●` and earlier ones with `○`; `STATUS` is the Deployment's relationship to Production: `current`, `promoting`, `failed`, `stopped`, `previous` or `none`. Promotion and rollback compare-and-swap the Production generation, so two people moving Production at once cannot silently overwrite each other; a conflict is reported and the command can be retried after checking `tonbo deployments`. `tonbo
|
|
118
|
+
`tonbo deployments` (alias `tonbo deployments list`) marks the current Production Deployment with `●` and earlier ones with `○`; `STATUS` is the Deployment's relationship to Production: `current`, `promoting`, `failed`, `stopped`, `previous` or `none`. Promotion and rollback compare-and-swap the Production generation, so two people moving Production at once cannot silently overwrite each other; a conflict is reported and the command can be retried after checking `tonbo deployments`. `tonbo agent show` prints the Production Deployment and its state alongside the Agent addresses.
|
|
119
119
|
|
|
120
|
-
Use `tonbo
|
|
120
|
+
Use `tonbo agent show` to rediscover the username, application address and SSH command later. `tonbo login` registers public keys found at the conventional `~/.ssh/id_ed25519.pub`, `id_ecdsa.pub` and `id_rsa.pub` paths. Register a key at another path with `tonbo ssh-key add <path.pub>` and revoke a lost or retired key with `tonbo ssh-key remove SHA256:...`. The CLI is not part of the SSH connection; ordinary OpenSSH, `scp` and `rsync` connect directly:
|
|
121
121
|
|
|
122
122
|
```console
|
|
123
123
|
ssh my-project.my-account@tonbo.sh
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
The SSH user name is the
|
|
126
|
+
The SSH user name is the Agent qualified by its username; the signed public key identifies the Tonbo user and is checked against membership and IAM at connection time. The CLI resolves the Agent name in `.tonbo` and prints the server-authoritative destination, so users never need to remember or assemble a username. The shell and HTTP turns may coexist on the singleton runtime, allowing the shell to observe the Agent while it works. Session writer fencing protects durable conversation history; ordinary workspace files retain Linux process concurrency semantics.
|
|
127
127
|
|
|
128
128
|
Deploy does not create a hidden Session just to prewarm PI. The first real `tonbo run` starts the Session-bound PI RPC process; successful Turns keep that process hot, including across native Session switches. The process is disposable cache rather than durable state: pause, replacement and uncertain failures remove it, and the next Turn restores authority from the durable Session JSONL.
|
|
129
129
|
|
|
@@ -133,7 +133,7 @@ Deploy snapshots regular files under `.tonbo`, excluding `.git`, `node_modules`,
|
|
|
133
133
|
|
|
134
134
|
## Supported PI project shapes
|
|
135
135
|
|
|
136
|
-
### 1.
|
|
136
|
+
### 1. Agent-local Agent
|
|
137
137
|
|
|
138
138
|
Keep the normal PI project layout. Tonbo runs the same `AGENTS.md`, `.pi/APPEND_SYSTEM.md`, `.pi/settings.json`, `.pi/extensions`, `.pi/skills` and `.pi/prompts` that local `pi` loads:
|
|
139
139
|
|
|
@@ -182,7 +182,7 @@ model = "claude-sonnet-4-5"
|
|
|
182
182
|
|
|
183
183
|
`tonbo deploy` runs the build command before creating the source snapshot. The entrypoint must keep stdout exclusively for PI RPC and send logs to stderr. It receives `PI_CODING_AGENT_MODULE`, `PI_CODING_AGENT_DIR`, `PI_CODING_AGENT_SESSION_DIR`, `TONBO_PI_SESSION_FILE`, `TONBO_PI_SESSION_ID`, `TONBO_PI_PROVIDER`, `TONBO_PI_MODEL` and `TONBO_PI_RPC_PROTOCOL`. Load the platform PI SDK from `PI_CODING_AGENT_MODULE`, open `TONBO_PI_SESSION_FILE`, create an `AgentSessionRuntime`, and pass it to `runRpcMode()`. This lets the app customize tools and runtime services without forking PI while preserving Tonbo's durable Session and Turn protocol.
|
|
184
184
|
|
|
185
|
-
For a non-interactive invocation, provide a current Tonbo CLI OAuth access token; the committed `.tonbo` supplies the only
|
|
185
|
+
For a non-interactive invocation, provide a current Tonbo CLI OAuth access token; the committed `.tonbo` supplies the only Agent context:
|
|
186
186
|
|
|
187
187
|
```console
|
|
188
188
|
TONBO_ACCESS_TOKEN=... tonbo --json deploy
|
|
@@ -196,7 +196,25 @@ Node.js 22 or newer is required. Human OAuth tokens are stored at `${XDG_CONFIG_
|
|
|
196
196
|
- [Design documentation map](../../docs/design/README.md)
|
|
197
197
|
- [Agent source inspection and onboarding](../../docs/design/agent-source-onboarding.md)
|
|
198
198
|
- [Shared source inspector](../../packages/agent-source-inspector/README.md)
|
|
199
|
-
- [
|
|
200
|
-
- [
|
|
199
|
+
- [Agent resource model](../../docs/design/project-resource-model.md)
|
|
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
|
@@ -52,7 +52,7 @@ var TonboApi = class {
|
|
|
52
52
|
listProjects(oauthToken) {
|
|
53
53
|
return requestJson(
|
|
54
54
|
this.fetcher,
|
|
55
|
-
`${this.accountOrigin}/api/cli/
|
|
55
|
+
`${this.accountOrigin}/api/cli/agents`,
|
|
56
56
|
{
|
|
57
57
|
headers: { authorization: `Bearer ${oauthToken}` }
|
|
58
58
|
}
|
|
@@ -70,7 +70,7 @@ var TonboApi = class {
|
|
|
70
70
|
createProject(oauthToken, name, organizationId) {
|
|
71
71
|
return requestJson(
|
|
72
72
|
this.fetcher,
|
|
73
|
-
`${this.accountOrigin}/api/cli/
|
|
73
|
+
`${this.accountOrigin}/api/cli/agents`,
|
|
74
74
|
{
|
|
75
75
|
method: "POST",
|
|
76
76
|
headers: {
|
|
@@ -116,7 +116,7 @@ var TonboApi = class {
|
|
|
116
116
|
exchangeManagementToken(oauthToken, projectId) {
|
|
117
117
|
return requestJson(
|
|
118
118
|
this.fetcher,
|
|
119
|
-
`${this.accountOrigin}/api/cli/
|
|
119
|
+
`${this.accountOrigin}/api/cli/agents/${projectId}/token`,
|
|
120
120
|
{
|
|
121
121
|
method: "POST",
|
|
122
122
|
headers: { authorization: `Bearer ${oauthToken}` }
|
|
@@ -136,7 +136,7 @@ var TonboApi = class {
|
|
|
136
136
|
sha256: bundle.sha256,
|
|
137
137
|
size_bytes: bundle.size_bytes
|
|
138
138
|
};
|
|
139
|
-
const bundlesPath = `/v1/
|
|
139
|
+
const bundlesPath = `/v1/agents/${projectId}/source-bundles`;
|
|
140
140
|
const prepared = await this.management("PUT", `${bundlesPath}/${bundle.sha256}`, token, {
|
|
141
141
|
format: descriptor.format,
|
|
142
142
|
size_bytes: descriptor.size_bytes
|
|
@@ -188,25 +188,25 @@ var TonboApi = class {
|
|
|
188
188
|
createDeployment(projectId, body, token) {
|
|
189
189
|
return this.management(
|
|
190
190
|
"POST",
|
|
191
|
-
`/v1/
|
|
191
|
+
`/v1/agents/${projectId}/deployments`,
|
|
192
192
|
token,
|
|
193
193
|
body
|
|
194
194
|
).then((response) => response.data);
|
|
195
195
|
}
|
|
196
196
|
listDeployments(projectId, token) {
|
|
197
|
-
return this.managementList(`/v1/
|
|
197
|
+
return this.managementList(`/v1/agents/${projectId}/deployments`, token);
|
|
198
198
|
}
|
|
199
199
|
getDeployment(projectId, deploymentId, token) {
|
|
200
200
|
return this.management(
|
|
201
201
|
"GET",
|
|
202
|
-
`/v1/
|
|
202
|
+
`/v1/agents/${projectId}/deployments/${deploymentId}`,
|
|
203
203
|
token
|
|
204
204
|
).then((response) => response.data);
|
|
205
205
|
}
|
|
206
206
|
getProduction(projectId, token) {
|
|
207
207
|
return this.management(
|
|
208
208
|
"GET",
|
|
209
|
-
`/v1/
|
|
209
|
+
`/v1/agents/${projectId}/production`,
|
|
210
210
|
token
|
|
211
211
|
).then(
|
|
212
212
|
(response) => response.data,
|
|
@@ -219,14 +219,14 @@ var TonboApi = class {
|
|
|
219
219
|
putProduction(projectId, body, token) {
|
|
220
220
|
return this.management(
|
|
221
221
|
"PUT",
|
|
222
|
-
`/v1/
|
|
222
|
+
`/v1/agents/${projectId}/production`,
|
|
223
223
|
token,
|
|
224
224
|
body
|
|
225
225
|
).then((response) => response.data);
|
|
226
226
|
}
|
|
227
227
|
listRollouts(projectId, token) {
|
|
228
228
|
return this.managementList(
|
|
229
|
-
`/v1/
|
|
229
|
+
`/v1/agents/${projectId}/production/rollouts`,
|
|
230
230
|
token
|
|
231
231
|
);
|
|
232
232
|
}
|
|
@@ -237,10 +237,10 @@ var TonboApi = class {
|
|
|
237
237
|
token,
|
|
238
238
|
turnId = randomUUID()
|
|
239
239
|
}) {
|
|
240
|
-
const projectPath = `/v1/
|
|
240
|
+
const projectPath = `/v1/agents/${projectId}`;
|
|
241
241
|
const production = await this.getProduction(projectId, token);
|
|
242
242
|
if (!production)
|
|
243
|
-
throw new Error("
|
|
243
|
+
throw new Error("Agent has no Production Deployment; run `tonbo deploy` first.");
|
|
244
244
|
if (production.observed_state !== "running")
|
|
245
245
|
throw new Error(
|
|
246
246
|
`Production is ${production.observed_state}${production.last_error ? ` (${production.last_error})` : ""}; wait for it to be running.`
|
|
@@ -269,21 +269,21 @@ var TonboApi = class {
|
|
|
269
269
|
}) {
|
|
270
270
|
return this.management(
|
|
271
271
|
"GET",
|
|
272
|
-
`/v1/
|
|
272
|
+
`/v1/agents/${projectId}/sessions/${sessionId}/turns/${turnId}/events?after=${after}`,
|
|
273
273
|
token
|
|
274
274
|
);
|
|
275
275
|
}
|
|
276
276
|
listProjectSecrets(projectId, token) {
|
|
277
277
|
return this.management(
|
|
278
278
|
"GET",
|
|
279
|
-
`/v1/
|
|
279
|
+
`/v1/agents/${projectId}/secrets`,
|
|
280
280
|
token
|
|
281
281
|
).then((body) => body.data);
|
|
282
282
|
}
|
|
283
283
|
setProjectSecret(projectId, name, value, token) {
|
|
284
284
|
return this.management(
|
|
285
285
|
"PUT",
|
|
286
|
-
`/v1/
|
|
286
|
+
`/v1/agents/${projectId}/secrets/${encodeURIComponent(name)}`,
|
|
287
287
|
token,
|
|
288
288
|
{ value }
|
|
289
289
|
);
|
|
@@ -291,7 +291,7 @@ var TonboApi = class {
|
|
|
291
291
|
deleteProjectSecret(projectId, name, token) {
|
|
292
292
|
return this.management(
|
|
293
293
|
"DELETE",
|
|
294
|
-
`/v1/
|
|
294
|
+
`/v1/agents/${projectId}/secrets/${encodeURIComponent(name)}`,
|
|
295
295
|
token
|
|
296
296
|
);
|
|
297
297
|
}
|
|
@@ -1315,7 +1315,7 @@ async function validatePackageSource(root, source) {
|
|
|
1315
1315
|
throw error;
|
|
1316
1316
|
}
|
|
1317
1317
|
if (!metadata.isDirectory() || metadata.isSymbolicLink()) {
|
|
1318
|
-
throw new Error(`Local PI package ${source} must resolve to a real
|
|
1318
|
+
throw new Error(`Local PI package ${source} must resolve to a real agent directory.`);
|
|
1319
1319
|
}
|
|
1320
1320
|
return;
|
|
1321
1321
|
}
|
|
@@ -1506,7 +1506,7 @@ function validateProjectName(name) {
|
|
|
1506
1506
|
const valid = name.length >= PROJECT_NAME_RULE.minLength && name.length <= PROJECT_NAME_RULE.maxLength && PROJECT_NAME_PATTERN.test(name) && !RESERVED_PROJECT_NAMES.has(name);
|
|
1507
1507
|
if (!valid) {
|
|
1508
1508
|
throw new Error(
|
|
1509
|
-
`
|
|
1509
|
+
`Agent name must be ${PROJECT_NAME_RULE.minLength}-${PROJECT_NAME_RULE.maxLength} lowercase letters, digits, or single hyphens, start with a letter, and not be reserved.`
|
|
1510
1510
|
);
|
|
1511
1511
|
}
|
|
1512
1512
|
}
|
|
@@ -1526,7 +1526,7 @@ async function resolveProject(deps) {
|
|
|
1526
1526
|
const root = await findDeclarationRoot(deps.cwd());
|
|
1527
1527
|
const declaration = await loadDeclaration(root);
|
|
1528
1528
|
if (!declaration.agent) {
|
|
1529
|
-
throw new Error("No
|
|
1529
|
+
throw new Error("No Agent is configured in .tonbo. Run `tonbo agent use <agent>` first.");
|
|
1530
1530
|
}
|
|
1531
1531
|
const oauthToken = await deps.auth.accessToken();
|
|
1532
1532
|
return {
|
|
@@ -1541,10 +1541,10 @@ function selectProject(projects, selector) {
|
|
|
1541
1541
|
const matches = projects.filter(
|
|
1542
1542
|
(project) => project.id === selector || project.name === normalized || project.publicHostname === normalized
|
|
1543
1543
|
);
|
|
1544
|
-
if (matches.length === 0) throw new Error(`
|
|
1544
|
+
if (matches.length === 0) throw new Error(`Agent ${selector} was not found in your account.`);
|
|
1545
1545
|
if (matches.length > 1)
|
|
1546
|
-
throw new Error(`
|
|
1547
|
-
if (matches[0].status !== "active") throw new Error(`
|
|
1546
|
+
throw new Error(`Agent name ${selector} is ambiguous; use its full hostname or ID.`);
|
|
1547
|
+
if (matches[0].status !== "active") throw new Error(`Agent ${selector} is not active.`);
|
|
1548
1548
|
return matches[0];
|
|
1549
1549
|
}
|
|
1550
1550
|
async function initCommand(deps, options) {
|
|
@@ -1618,7 +1618,7 @@ async function initCommand(deps, options) {
|
|
|
1618
1618
|
value: "save"
|
|
1619
1619
|
},
|
|
1620
1620
|
{
|
|
1621
|
-
description: "Change the
|
|
1621
|
+
description: "Change the agent, Harness, execution mode, model, or SDK entrypoint.",
|
|
1622
1622
|
name: "Edit configuration",
|
|
1623
1623
|
value: "edit"
|
|
1624
1624
|
},
|
|
@@ -1702,7 +1702,7 @@ async function initCommand(deps, options) {
|
|
|
1702
1702
|
} catch (error) {
|
|
1703
1703
|
if (createdProject) {
|
|
1704
1704
|
throw new Error(
|
|
1705
|
-
`Created
|
|
1705
|
+
`Created agent ${createdProject.name}, but could not write ${DECLARATION_FILENAME}. Fix the file and run \`tonbo agent use ${createdProject.publicHostname}\`.`,
|
|
1706
1706
|
{ cause: error }
|
|
1707
1707
|
);
|
|
1708
1708
|
}
|
|
@@ -1711,14 +1711,14 @@ async function initCommand(deps, options) {
|
|
|
1711
1711
|
const driverSummary = driver === "command" ? `PI SDK app
|
|
1712
1712
|
Build: ${buildCommand?.join(" ")}
|
|
1713
1713
|
Entrypoint: node ${entry}` : inspection.pi.packageCount > 0 ? `PI CLI with ${inspection.pi.packageCount} package${inspection.pi.packageCount === 1 ? "" : "s"}` : "PI CLI";
|
|
1714
|
-
const projectSummary = createdProject ? `
|
|
1714
|
+
const projectSummary = createdProject ? `Agent: ${createdProject.name} (${createdProject.publicHostname})
|
|
1715
1715
|
Organization: ${createdProject.organizationName}
|
|
1716
1716
|
Application: https://${createdProject.publicHostname}
|
|
1717
|
-
SSH after deploy: ssh ${createdProject.sshDestination}` : projectPlan.kind === "existing" ? `
|
|
1717
|
+
SSH after deploy: ssh ${createdProject.sshDestination}` : projectPlan.kind === "existing" ? `Agent: ${projectPlan.name ? `${projectPlan.name} (${projectPlan.publicHostname})` : projectPlan.publicHostname}${projectPlan.organizationName ? `
|
|
1718
1718
|
Organization: ${projectPlan.organizationName}` : ""}${projectPlan.sshDestination ? `
|
|
1719
|
-
SSH after deploy: ssh ${projectPlan.sshDestination}` : ""}` : "Next: tonbo
|
|
1719
|
+
SSH after deploy: ssh ${projectPlan.sshDestination}` : ""}` : "Next: tonbo agent create <name>";
|
|
1720
1720
|
deps.output({
|
|
1721
|
-
message: `${createdProject ? `Created
|
|
1721
|
+
message: `${createdProject ? `Created agent ${createdProject.name} and` : exists ? "Updated" : "Created"} ${DECLARATION_FILENAME}.
|
|
1722
1722
|
${projectSummary}
|
|
1723
1723
|
Harness: PI
|
|
1724
1724
|
Mode: ${driverSummary}${projectPlan.kind === "later" ? "" : "\nNext: tonbo deploy"}`,
|
|
@@ -1728,25 +1728,25 @@ Mode: ${driverSummary}${projectPlan.kind === "later" ? "" : "\nNext: tonbo deplo
|
|
|
1728
1728
|
}
|
|
1729
1729
|
function initSaveLabel(exists, project) {
|
|
1730
1730
|
if (project.kind === "create") {
|
|
1731
|
-
return exists ? `Create
|
|
1731
|
+
return exists ? `Create agent and replace ${DECLARATION_FILENAME}` : `Create agent and ${DECLARATION_FILENAME}`;
|
|
1732
1732
|
}
|
|
1733
1733
|
return exists ? `Replace ${DECLARATION_FILENAME}` : `Create ${DECLARATION_FILENAME}`;
|
|
1734
1734
|
}
|
|
1735
1735
|
async function selectInitProject(deps, root) {
|
|
1736
1736
|
for (; ; ) {
|
|
1737
|
-
const action = await deps.select("How should this
|
|
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
|
-
name: "Create a new
|
|
1740
|
+
name: "Create a new agent",
|
|
1741
1741
|
value: "create"
|
|
1742
1742
|
},
|
|
1743
1743
|
{
|
|
1744
|
-
description: "Bind this source tree to one
|
|
1745
|
-
name: "Use an existing
|
|
1744
|
+
description: "Bind this source tree to one agent you can access.",
|
|
1745
|
+
name: "Use an existing agent",
|
|
1746
1746
|
value: "existing"
|
|
1747
1747
|
},
|
|
1748
1748
|
{
|
|
1749
|
-
description: "Write an unbound declaration and configure its
|
|
1749
|
+
description: "Write an unbound declaration and configure its agent later.",
|
|
1750
1750
|
name: "Set up later",
|
|
1751
1751
|
value: "later"
|
|
1752
1752
|
}
|
|
@@ -1756,7 +1756,7 @@ async function selectInitProject(deps, root) {
|
|
|
1756
1756
|
const organization = await selectInitOrganization(deps);
|
|
1757
1757
|
const defaultName = projectNameSuggestion(path4.basename(root)) || "tonbo-agent";
|
|
1758
1758
|
for (; ; ) {
|
|
1759
|
-
const answer = (await deps.prompt(`
|
|
1759
|
+
const answer = (await deps.prompt(`Agent name [${defaultName}]: `)).trim().toLowerCase();
|
|
1760
1760
|
const name = answer || defaultName;
|
|
1761
1761
|
try {
|
|
1762
1762
|
validateProjectName(name);
|
|
@@ -1768,7 +1768,7 @@ async function selectInitProject(deps, root) {
|
|
|
1768
1768
|
};
|
|
1769
1769
|
} catch (error) {
|
|
1770
1770
|
deps.output({
|
|
1771
|
-
message: error instanceof Error ? error.message : "
|
|
1771
|
+
message: error instanceof Error ? error.message : "Agent name is invalid."
|
|
1772
1772
|
});
|
|
1773
1773
|
}
|
|
1774
1774
|
}
|
|
@@ -1778,11 +1778,11 @@ async function selectInitProject(deps, root) {
|
|
|
1778
1778
|
(project2) => project2.status === "active"
|
|
1779
1779
|
);
|
|
1780
1780
|
if (projects.length === 0) {
|
|
1781
|
-
deps.output({ message: "No active
|
|
1781
|
+
deps.output({ message: "No active agents are available. Create a new agent instead." });
|
|
1782
1782
|
continue;
|
|
1783
1783
|
}
|
|
1784
1784
|
const id = await deps.select(
|
|
1785
|
-
"Which
|
|
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}`,
|
|
@@ -1816,7 +1816,7 @@ async function selectInitOrganization(deps) {
|
|
|
1816
1816
|
throw new Error("No organization lets you create a project. Ask an admin or owner.");
|
|
1817
1817
|
if (organizations.length === 1) return organizations[0];
|
|
1818
1818
|
const id = await deps.select(
|
|
1819
|
-
"Which organization should own the new
|
|
1819
|
+
"Which organization should own the new agent?",
|
|
1820
1820
|
organizations.map((organization) => ({
|
|
1821
1821
|
description: organization.role,
|
|
1822
1822
|
name: organization.name,
|
|
@@ -1829,7 +1829,7 @@ async function selectHarness(deps) {
|
|
|
1829
1829
|
return await deps.select(
|
|
1830
1830
|
"Which supported Harness should Tonbo use?",
|
|
1831
1831
|
supportedHarnesses.map((supported) => ({
|
|
1832
|
-
description: `Run this
|
|
1832
|
+
description: `Run this agent with the ${supported.command} command.`,
|
|
1833
1833
|
name: `${supported.name} (\`${supported.command}\`)`,
|
|
1834
1834
|
value: supported.id
|
|
1835
1835
|
}))
|
|
@@ -1843,7 +1843,7 @@ function renderInitSummary(project, harness, driver, model, entry, buildCommand)
|
|
|
1843
1843
|
const lines = [
|
|
1844
1844
|
"",
|
|
1845
1845
|
"Tonbo Agent configuration:",
|
|
1846
|
-
`
|
|
1846
|
+
` Agent: ${initProjectSummary(project)}`,
|
|
1847
1847
|
` Harness: ${harnessName(harness)}`,
|
|
1848
1848
|
` Execution: ${driver === "native" ? "PI CLI (`pi`)" : "PI SDK app"}`,
|
|
1849
1849
|
` Model: ${model}`
|
|
@@ -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({
|
|
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) {
|
|
@@ -1943,7 +1946,7 @@ async function projectUseCommand(deps, selector, force = false) {
|
|
|
1943
1946
|
const currentLabel = current?.publicHostname ?? declaration.agent;
|
|
1944
1947
|
if (!deps.interactive()) {
|
|
1945
1948
|
throw new Error(
|
|
1946
|
-
`.tonbo already uses
|
|
1949
|
+
`.tonbo already uses agent ${currentLabel}. Pass --force to rebind it to ${project.publicHostname}.`
|
|
1947
1950
|
);
|
|
1948
1951
|
}
|
|
1949
1952
|
const action = await deps.select(
|
|
@@ -1954,19 +1957,19 @@ async function projectUseCommand(deps, selector, force = false) {
|
|
|
1954
1957
|
]
|
|
1955
1958
|
);
|
|
1956
1959
|
if (action !== "rebind") {
|
|
1957
|
-
deps.output({ message: `Cancelled. .tonbo still uses
|
|
1960
|
+
deps.output({ message: `Cancelled. .tonbo still uses agent ${currentLabel}.` });
|
|
1958
1961
|
return;
|
|
1959
1962
|
}
|
|
1960
1963
|
}
|
|
1961
1964
|
await bindDeclarationProject(root, project.publicHostname);
|
|
1962
|
-
deps.output({ message: `Bound .tonbo to
|
|
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());
|
|
1966
1969
|
const declaration = await loadDeclaration(root);
|
|
1967
1970
|
if (declaration.agent) {
|
|
1968
1971
|
throw new Error(
|
|
1969
|
-
`.tonbo is already bound to
|
|
1972
|
+
`.tonbo is already bound to agent ${declaration.agent}. Run \`tonbo agent use <agent>\` to review a rebind.`
|
|
1970
1973
|
);
|
|
1971
1974
|
}
|
|
1972
1975
|
const oauthToken = await deps.auth.accessToken();
|
|
@@ -1976,11 +1979,11 @@ async function projectCreateCommand(deps, name) {
|
|
|
1976
1979
|
await bindDeclarationProject(root, project.publicHostname);
|
|
1977
1980
|
} catch (error) {
|
|
1978
1981
|
throw new Error(
|
|
1979
|
-
`Created
|
|
1982
|
+
`Created agent ${project.name}, but could not bind ${DECLARATION_FILENAME}. Fix the file and run \`tonbo agent use ${project.publicHostname}\`.`,
|
|
1980
1983
|
{ cause: error }
|
|
1981
1984
|
);
|
|
1982
1985
|
}
|
|
1983
|
-
deps.output({ message: `Created
|
|
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);
|
|
@@ -1999,7 +2002,7 @@ async function deployCommand(deps, options = { promote: true }) {
|
|
|
1999
2002
|
const { deployment } = result;
|
|
2000
2003
|
const shortId = shortDeploymentId(deployment.id);
|
|
2001
2004
|
const lines = [
|
|
2002
|
-
options.promote ? `Deployed
|
|
2005
|
+
options.promote ? `Deployed agent ${project.name}.` : `Created Deployment ${deploymentName(deployment)} (${shortId}) for agent ${project.name} without promoting it.`,
|
|
2003
2006
|
`Organization: ${project.organizationName}`,
|
|
2004
2007
|
`Deployment: ${deploymentName(deployment)} (${shortId})`,
|
|
2005
2008
|
`Source: ${deploymentSourceLabel(deployment)}`,
|
|
@@ -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,16 +2039,23 @@ 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);
|
|
2046
2056
|
const deployment = production ? await deps.api.getDeployment(project.id, production.deployment_id, token) : null;
|
|
2047
2057
|
const lines = [
|
|
2048
|
-
`
|
|
2058
|
+
`agent: ${project.name}`,
|
|
2049
2059
|
`Organization: ${project.organizationName}`,
|
|
2050
2060
|
`application: https://${project.publicHostname}`,
|
|
2051
2061
|
`ssh: ssh ${project.sshDestination}`
|
|
@@ -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);
|
|
@@ -2124,8 +2134,8 @@ async function deploymentsListCommand(deps) {
|
|
|
2124
2134
|
formatTimestamp(deployment.created_at),
|
|
2125
2135
|
deployment.created_by_user_id ? shortDeploymentId(deployment.created_by_user_id) : ""
|
|
2126
2136
|
])
|
|
2127
|
-
) : `No Deployments exist for
|
|
2128
|
-
deps.output({ message, project, production, deployments });
|
|
2137
|
+
) : `No Deployments exist for agent ${project.name}. Run \`tonbo deploy\` to create one.`;
|
|
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
|
}
|
|
@@ -2197,7 +2207,7 @@ async function deploymentsRollbackCommand(deps, prefix) {
|
|
|
2197
2207
|
)?.previous_deployment_id;
|
|
2198
2208
|
if (!previousId) {
|
|
2199
2209
|
throw new Error(
|
|
2200
|
-
`
|
|
2210
|
+
`Agent ${project.name} has no previous Production Deployment to roll back to. Name one with \`tonbo deployments rollback <id>\`.`
|
|
2201
2211
|
);
|
|
2202
2212
|
}
|
|
2203
2213
|
target = await deps.api.getDeployment(project.id, previousId, token);
|
|
@@ -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
|
}
|
|
@@ -2229,7 +2239,7 @@ async function moveProduction(deps, projectId, target, token) {
|
|
|
2229
2239
|
function describeProductionMove(project, move, verb) {
|
|
2230
2240
|
const { deployment, previous } = move;
|
|
2231
2241
|
const name = `${deploymentName(deployment)} (${shortDeploymentId(deployment.id)})`;
|
|
2232
|
-
const headline = previous?.deployment_id === deployment.id ? `Deployment ${name} is already Production for
|
|
2242
|
+
const headline = previous?.deployment_id === deployment.id ? `Deployment ${name} is already Production for agent ${project.name}; requested it to be running.` : `${verb} ${name} to Production for agent ${project.name}${previous ? ` (from ${shortDeploymentId(previous.deployment_id)})` : ""}.`;
|
|
2233
2243
|
return `${headline}
|
|
2234
2244
|
Production: ${productionStateLabel(deployment)}
|
|
2235
2245
|
Application: https://${project.publicHostname}`;
|
|
@@ -2245,8 +2255,8 @@ async function secretListCommand(deps) {
|
|
|
2245
2255
|
const { project, token } = await projectManagement(deps);
|
|
2246
2256
|
const secrets = await deps.api.listProjectSecrets(project.id, token);
|
|
2247
2257
|
deps.output({
|
|
2248
|
-
message: secrets.length ? secrets.map((secret) => secret.name).join("\n") : "No
|
|
2249
|
-
project,
|
|
2258
|
+
message: secrets.length ? secrets.map((secret) => secret.name).join("\n") : "No agent secrets are configured.",
|
|
2259
|
+
agent: project,
|
|
2250
2260
|
secrets
|
|
2251
2261
|
});
|
|
2252
2262
|
}
|
|
@@ -2255,15 +2265,15 @@ async function secretSetCommand(deps, name, options) {
|
|
|
2255
2265
|
const { project, token } = await projectManagement(deps);
|
|
2256
2266
|
const secret = await deps.api.setProjectSecret(project.id, name, value, token);
|
|
2257
2267
|
deps.output({
|
|
2258
|
-
message: `Set
|
|
2259
|
-
project,
|
|
2268
|
+
message: `Set agent secret ${secret.name}. Redeploy to replace the active runtime with this value.`,
|
|
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
|
|
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
|
|
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,21 +2593,22 @@ function createProgram(dependencies = createDependencies) {
|
|
|
2583
2593
|
})
|
|
2584
2594
|
);
|
|
2585
2595
|
});
|
|
2586
|
-
const project = program.command("
|
|
2587
|
-
project.command("create <name>").description("create and bind
|
|
2588
|
-
|
|
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))));
|
|
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 <
|
|
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
|
|
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
|
);
|
|
2600
|
-
const deployments = program.command("deployments").description("list and move between the immutable Deployments of the bound
|
|
2611
|
+
const deployments = program.command("deployments").description("list and move between the immutable Deployments of the bound agent");
|
|
2601
2612
|
deployments.command("list", { isDefault: true }).description("list Deployments, newest first").action(async () => deploymentsListCommand(dependencies(jsonOutput(program))));
|
|
2602
2613
|
deployments.command("show <deployment>").description("show one Deployment and its Rollouts by id prefix").action(
|
|
2603
2614
|
async (prefix) => deploymentsShowCommand(dependencies(jsonOutput(program)), prefix)
|
|
@@ -2608,10 +2619,10 @@ function createProgram(dependencies = createDependencies) {
|
|
|
2608
2619
|
deployments.command("rollback [deployment]").description("move Production back to the previous Production Deployment, or to a named one").action(
|
|
2609
2620
|
async (prefix) => deploymentsRollbackCommand(dependencies(jsonOutput(program)), prefix)
|
|
2610
2621
|
);
|
|
2611
|
-
program.command("run <prompt>").description("run one prompt in a durable
|
|
2622
|
+
program.command("run <prompt>").description("run one prompt in a durable agent session").option("--session <session>", "resume an existing Agent Session UUID").action(
|
|
2612
2623
|
async (prompt, options) => runCommand(dependencies(jsonOutput(program)), prompt, options)
|
|
2613
2624
|
);
|
|
2614
|
-
const secret = program.command("secret").description("manage encrypted environment secrets for the
|
|
2625
|
+
const secret = program.command("secret").description("manage encrypted environment secrets for the agent service");
|
|
2615
2626
|
secret.command("list").action(async () => secretListCommand(dependencies(jsonOutput(program))));
|
|
2616
2627
|
secret.command("set <name>").description("set a secret from an environment variable (the same name by default)").option("--from-env <name>", "read the value from another environment variable").action(
|
|
2617
2628
|
async (name, options) => secretSetCommand(dependencies(jsonOutput(program)), name, options)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tonbo/cli",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Deploy
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Deploy persistent Agents and manage their Machines from the command line.",
|
|
5
5
|
"homepage": "https://tonbo.dev",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/tonbo-io/cloud/issues"
|