@ponderbot/cli 0.1.0-alpha.25 → 0.1.0-alpha.27
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 +39 -0
- package/dist/main.js +47 -24
- package/dist/main.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -90,6 +90,45 @@ uses `@ponderbot/sdk` for authoring and local loading. The CLI bundles the SDK
|
|
|
90
90
|
Worker Entry into the artifact. A project can set `worker.build.dockerfile` when
|
|
91
91
|
it needs a custom system image or install process.
|
|
92
92
|
|
|
93
|
+
## Environment selection
|
|
94
|
+
|
|
95
|
+
Every command resolves one Project environment from `ponderbot/config.ts`. The
|
|
96
|
+
CLI selects the environment in this order:
|
|
97
|
+
|
|
98
|
+
1. `--env <name>` on the command.
|
|
99
|
+
2. A non-empty `PONDERBOT_ENV` in the process environment.
|
|
100
|
+
3. The `development` environment.
|
|
101
|
+
|
|
102
|
+
A named environment (`--env` or `PONDERBOT_ENV`) is the source of truth:
|
|
103
|
+
|
|
104
|
+
- The URL comes from the environment `url`. `PONDERBOT_URL` does not change
|
|
105
|
+
it.
|
|
106
|
+
- The token comes from the environment `tokenEnv` variable. `PONDERBOT_TOKEN`
|
|
107
|
+
is only a fallback when that variable is not set.
|
|
108
|
+
- The Space comes from `--space` or the environment `spaceId`. A named
|
|
109
|
+
environment never reads `PONDERBOT_SPACE_ID`. Space-scoped commands exit 2
|
|
110
|
+
when neither `--space` nor `spaceId` is set. `spaces list` and
|
|
111
|
+
`spaces create` do not need a Space.
|
|
112
|
+
|
|
113
|
+
The default `development` environment keeps the `ponder start` contract:
|
|
114
|
+
`PONDERBOT_URL`, `PONDERBOT_SPACE_ID`, and `PONDERBOT_TOKEN` override the
|
|
115
|
+
environment values when they are set. `--space` still wins over both.
|
|
116
|
+
|
|
117
|
+
Example with a `.env` file that `ponder start` printed:
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
export PONDERBOT_URL=http://127.0.0.1:4000
|
|
121
|
+
export PONDERBOT_TOKEN_PRODUCTION=prod-token
|
|
122
|
+
ponder spaces list --env production
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The command lists the Spaces of the `production` URL with `prod-token`. The
|
|
126
|
+
local `PONDERBOT_URL` does not change the target.
|
|
127
|
+
|
|
128
|
+
Mutating commands, such as `manifest deploy`, `spaces create`, and
|
|
129
|
+
`action run`, print the resolved target. Human output starts with `environment`
|
|
130
|
+
and `base URL` lines. JSON output adds the `environment` and `base_url` keys.
|
|
131
|
+
|
|
93
132
|
Useful space commands:
|
|
94
133
|
|
|
95
134
|
```sh
|
package/dist/main.js
CHANGED
|
@@ -31,6 +31,7 @@ const resolveProject = async () => {
|
|
|
31
31
|
};
|
|
32
32
|
const resolveConfig = async (envName, spaceId) => requireExecutionSpace(await resolveEnvironmentConfig(envName), spaceId);
|
|
33
33
|
const resolveProjectReleaseConfig = async (envName) => resolveEnvironmentConfig(envName, { resolveApplicationOrigin: true });
|
|
34
|
+
const resolveRuntimeConfig = async (envName) => resolveEnvironmentConfig(envName);
|
|
34
35
|
const resolveDevConfig = async (envName) => requireExecutionSpace(await resolveEnvironmentConfig(envName ?? "development", {
|
|
35
36
|
requireDevAllowed: true,
|
|
36
37
|
resolveApplicationOrigin: true,
|
|
@@ -72,7 +73,7 @@ const resolveEnvironmentConfig = async (envName, options = {}) => {
|
|
|
72
73
|
};
|
|
73
74
|
const requireExecutionSpace = (config, spaceId) => {
|
|
74
75
|
const resolvedSpaceId = spaceId !== void 0 && spaceId.length > 0 ? spaceId : config.spaceId;
|
|
75
|
-
if (resolvedSpaceId === void 0 || resolvedSpaceId.length === 0) return exitConfig(`set the execution Space with --space
|
|
76
|
+
if (resolvedSpaceId === void 0 || resolvedSpaceId.length === 0) return exitConfig(`set the execution Space with --space or spaceId for environment "${config.environment}" in ponderbot/config.ts`);
|
|
76
77
|
return {
|
|
77
78
|
...config,
|
|
78
79
|
spaceId: resolvedSpaceId
|
|
@@ -90,17 +91,23 @@ const clientFor = (config) => createClient({
|
|
|
90
91
|
token: config.token,
|
|
91
92
|
spaceId: config.spaceId
|
|
92
93
|
});
|
|
94
|
+
const withResolvedTarget = (config, result) => ({
|
|
95
|
+
...result,
|
|
96
|
+
environment: config.environment,
|
|
97
|
+
base_url: config.url
|
|
98
|
+
});
|
|
93
99
|
//#endregion
|
|
94
100
|
//#region src/deployment-environment.ts
|
|
95
101
|
const INERT_SOURCE_SETTINGS = {
|
|
96
102
|
allow_schedules: false,
|
|
103
|
+
allow_persistent_development_schedules: false,
|
|
97
104
|
allow_webhooks: false,
|
|
98
105
|
allow_manual_triggers: false
|
|
99
106
|
};
|
|
100
107
|
const reconcileDeploymentEnvironment = async (client, config) => {
|
|
101
108
|
if (config.environmentRole === "release-source") {
|
|
102
109
|
const { settings } = await client.spaces.settings.update(INERT_SOURCE_SETTINGS);
|
|
103
|
-
if (settings.allow_schedules !== false || settings.allow_webhooks !== false || settings.allow_manual_triggers !== false) throw new Error("release-source Space settings did not become execution-inert");
|
|
110
|
+
if (settings.allow_schedules !== false || settings.allow_persistent_development_schedules !== false || settings.allow_webhooks !== false || settings.allow_manual_triggers !== false) throw new Error("release-source Space settings did not become execution-inert");
|
|
104
111
|
}
|
|
105
112
|
};
|
|
106
113
|
//#endregion
|
|
@@ -349,6 +356,14 @@ const formatError = (error) => {
|
|
|
349
356
|
return String(error);
|
|
350
357
|
};
|
|
351
358
|
const lines = (data) => {
|
|
359
|
+
if (isRecord$1(data) && typeof data.environment === "string" && typeof data.base_url === "string") {
|
|
360
|
+
const { environment, base_url: baseUrl, ...result } = data;
|
|
361
|
+
return [
|
|
362
|
+
`environment ${environment}`,
|
|
363
|
+
`base URL ${baseUrl}`,
|
|
364
|
+
...lines(result)
|
|
365
|
+
];
|
|
366
|
+
}
|
|
352
367
|
if (isRecord$1(data) && isRecord$1(data.release) && isRecord$1(data.resources)) return releaseCatalogLines(data.release, data.resources);
|
|
353
368
|
if (isStartedDevStack(data)) return [
|
|
354
369
|
"Ponderbot dev stack ready.",
|
|
@@ -1780,7 +1795,7 @@ const providerAuth = async (options) => {
|
|
|
1780
1795
|
}
|
|
1781
1796
|
if (options.allSpaces === true) await client.providerBindings.authorize(binding.id, { allSpaces: true });
|
|
1782
1797
|
else await client.providerBindings.authorize(binding.id, { spaceIds: sharedSpaceIds });
|
|
1783
|
-
return providerAuthResult(provider, method, spaceId, {
|
|
1798
|
+
return providerAuthResult(provider, method, spaceId, config.environment, config.url, {
|
|
1784
1799
|
bindingId: binding.id,
|
|
1785
1800
|
allSpaces: options.allSpaces === true,
|
|
1786
1801
|
spaceIds: options.allSpaces === true ? void 0 : sharedSpaceIds
|
|
@@ -1792,16 +1807,16 @@ const providerAuth = async (options) => {
|
|
|
1792
1807
|
provider,
|
|
1793
1808
|
apiKey
|
|
1794
1809
|
});
|
|
1795
|
-
return providerAuthResult(provider, method, spaceId);
|
|
1810
|
+
return providerAuthResult(provider, method, spaceId, config.environment, config.url);
|
|
1796
1811
|
}
|
|
1797
1812
|
if (!canPrompt()) throw new Error("OAuth login needs an interactive terminal. Run locally with a browser, or rerun with --no-browser to paste the callback URL.");
|
|
1798
1813
|
await authorizeOAuthLogin(() => client.modelProviders.startOAuthLogin(spaceId, provider), (authorizationResponse, state) => client.modelProviders.completeOAuthLogin(spaceId, provider, {
|
|
1799
1814
|
authorizationResponse,
|
|
1800
1815
|
state
|
|
1801
1816
|
}), options.browser !== false);
|
|
1802
|
-
return providerAuthResult(provider, method, spaceId);
|
|
1817
|
+
return providerAuthResult(provider, method, spaceId, config.environment, config.url);
|
|
1803
1818
|
};
|
|
1804
|
-
const providerAuthResult = (provider, method, spaceId, shared) => ({
|
|
1819
|
+
const providerAuthResult = (provider, method, spaceId, environment, baseUrl, shared) => ({
|
|
1805
1820
|
type: "provider_auth",
|
|
1806
1821
|
status: "saved",
|
|
1807
1822
|
provider,
|
|
@@ -1810,7 +1825,9 @@ const providerAuthResult = (provider, method, spaceId, shared) => ({
|
|
|
1810
1825
|
binding_id: shared?.bindingId,
|
|
1811
1826
|
all_spaces: shared?.allSpaces,
|
|
1812
1827
|
space_ids: shared?.spaceIds,
|
|
1813
|
-
smoke_test: "ponder spaces show"
|
|
1828
|
+
smoke_test: "ponder spaces show",
|
|
1829
|
+
environment,
|
|
1830
|
+
base_url: baseUrl
|
|
1814
1831
|
});
|
|
1815
1832
|
const resolveProvider = async (value, entries) => {
|
|
1816
1833
|
const providers = entries.map((entry) => entry.id);
|
|
@@ -2361,10 +2378,10 @@ manifest.command("deploy").option("--env <name>", "environment").option("--image
|
|
|
2361
2378
|
});
|
|
2362
2379
|
printManifestDiagnostics(plan.instructionBudgets, plan.warnings);
|
|
2363
2380
|
const release = await client.projects.releases.deploy(config.projectDefinition.name, config.environment, plan.manifest, config.sourceName, void 0, config.applicationOrigin);
|
|
2364
|
-
print(versionBump === void 0 ? release : {
|
|
2381
|
+
print(withResolvedTarget(config, versionBump === void 0 ? release : {
|
|
2365
2382
|
...release,
|
|
2366
2383
|
version_bump: versionBump
|
|
2367
|
-
}, program.opts());
|
|
2384
|
+
}), program.opts());
|
|
2368
2385
|
} catch (error) {
|
|
2369
2386
|
fail(error, error instanceof WorkerImageError ? 2 : 1);
|
|
2370
2387
|
}
|
|
@@ -2378,19 +2395,19 @@ manifest.command("dev").option("--env <name>", "environment").description("watch
|
|
|
2378
2395
|
});
|
|
2379
2396
|
const spaces = program.command("spaces").description("manage runtime spaces");
|
|
2380
2397
|
spaces.command("list").option("--env <name>", "environment").description("list spaces").action(async (options) => {
|
|
2381
|
-
const config = await
|
|
2398
|
+
const config = await resolveRuntimeConfig(options.env);
|
|
2382
2399
|
await runSpacesCommand("spaces:read", "*", async () => {
|
|
2383
2400
|
print({ spaces: await listSpaces(clientFor(config)) }, program.opts());
|
|
2384
2401
|
});
|
|
2385
2402
|
});
|
|
2386
2403
|
spaces.command("create <spaceId>").option("--name <name>", "space name").option("--env <name>", "environment").description("create a space").action(async (spaceId, options) => {
|
|
2387
|
-
const config = await
|
|
2404
|
+
const config = await resolveRuntimeConfig(options.env);
|
|
2388
2405
|
await runSpacesCommand("spaces:write", "*", async () => {
|
|
2389
2406
|
try {
|
|
2390
|
-
print(await clientFor(config).spaces.create({
|
|
2407
|
+
print(withResolvedTarget(config, await clientFor(config).spaces.create({
|
|
2391
2408
|
id: spaceId,
|
|
2392
2409
|
name: options.name ?? spaceId
|
|
2393
|
-
}), program.opts());
|
|
2410
|
+
})), program.opts());
|
|
2394
2411
|
} catch (error) {
|
|
2395
2412
|
throw spaceCreateError(error, spaceId);
|
|
2396
2413
|
}
|
|
@@ -2422,7 +2439,7 @@ spaces.command("budget [spaceId]").option("--set <file>", "replace budget from a
|
|
|
2422
2439
|
print(await client.spaces.budget.get(resolvedSpaceId), program.opts());
|
|
2423
2440
|
return;
|
|
2424
2441
|
}
|
|
2425
|
-
print(await client.spaces.budget.set(await readJsonFile(options.set), resolvedSpaceId), program.opts());
|
|
2442
|
+
print(withResolvedTarget(config, await client.spaces.budget.set(await readJsonFile(options.set), resolvedSpaceId)), program.opts());
|
|
2426
2443
|
});
|
|
2427
2444
|
});
|
|
2428
2445
|
program.command("provider").description("configure model provider credentials").command("auth").description("authenticate a model provider for a space").option("--env <name>", "environment").option("--space <spaceId>", "target space (defaults to the configured space)").option("--provider <name>", "anthropic | mistral | openai (skips the picker)").option("--method <method>", "api-key | oauth").option("--shared", "store one Runtime credential binding instead of a Space credential").option("--all-spaces", "authorize the shared binding for every Space").option("--spaces <spaceIds...>", "authorize the shared binding for selected Spaces").option("--no-browser", "print the Codex authorize URL and paste the callback URL").action(async (options) => {
|
|
@@ -2432,7 +2449,7 @@ const model = program.command("model").description("manage Space model policy");
|
|
|
2432
2449
|
model.command("add <modelRef>").requiredOption("--provider <name>", "anthropic | fake | mistral | openai").requiredOption("--model <name>", "provider model name").option("--capability <name...>", "declared model capabilities").option("--fallback <modelRef...>", "ordered fallback model refs").option("--space <spaceId>", "target space (defaults to the configured space)").option("--env <name>", "environment").description("add or update a model in the Space catalog").action(async (modelRef, options) => {
|
|
2433
2450
|
const config = await resolveConfig(options.env, options.space);
|
|
2434
2451
|
await runSpacesCommand("spaces:write", config.spaceId, async () => {
|
|
2435
|
-
print(await clientFor(config).models.upsert(modelRef, modelDefinitionInput(options)), program.opts());
|
|
2452
|
+
print(withResolvedTarget(config, await clientFor(config).models.upsert(modelRef, modelDefinitionInput(options))), program.opts());
|
|
2436
2453
|
});
|
|
2437
2454
|
});
|
|
2438
2455
|
model.command("list").option("--space <spaceId>", "target space (defaults to the configured space)").option("--env <name>", "environment").description("list models in the Space catalog").action(async (options) => {
|
|
@@ -2444,7 +2461,7 @@ model.command("list").option("--space <spaceId>", "target space (defaults to the
|
|
|
2444
2461
|
model.command("assign <agentRef> <modelRef>").option("--space <spaceId>", "target space (defaults to the configured space)").option("--env <name>", "environment").description("assign a Space catalog model to an exact Agent ref").action(async (agentRef, modelRef, options) => {
|
|
2445
2462
|
const config = await resolveConfig(options.env, options.space);
|
|
2446
2463
|
await runSpacesCommand("spaces:write", config.spaceId, async () => {
|
|
2447
|
-
print(await clientFor(config).models.assign(agentRef, modelRef), program.opts());
|
|
2464
|
+
print(withResolvedTarget(config, await clientFor(config).models.assign(agentRef, modelRef)), program.opts());
|
|
2448
2465
|
});
|
|
2449
2466
|
});
|
|
2450
2467
|
model.command("assignments").option("--space <spaceId>", "target space (defaults to the configured space)").option("--env <name>", "environment").description("list exact Agent model assignments for a Space").action(async (options) => {
|
|
@@ -2463,7 +2480,8 @@ releases.command("catalog [releaseId]").option("--space <spaceId>", "target spac
|
|
|
2463
2480
|
print(await client.releases.catalog(resolvedReleaseId), program.opts());
|
|
2464
2481
|
});
|
|
2465
2482
|
program.command("rollback <releaseId>").option("--env <name>", "environment").description("roll back to a release").action(async (releaseId, options) => {
|
|
2466
|
-
|
|
2483
|
+
const config = await resolveConfig(options.env);
|
|
2484
|
+
print(withResolvedTarget(config, await clientFor(config).releases.rollback(releaseId)), program.opts());
|
|
2467
2485
|
});
|
|
2468
2486
|
program.command("runs").option("--type <type>", "run type").option("--status <status>", "run status").option("--env <name>", "environment").description("list runs").action(async (options) => {
|
|
2469
2487
|
print(await clientFor(await resolveConfig(options.env)).runs.list(Object.fromEntries([["type", options.type], ["status", options.status]].filter((entry) => typeof entry[1] === "string"))), program.opts());
|
|
@@ -2475,19 +2493,22 @@ program.command("run <type> <id>").option("--export", "export run bundle").optio
|
|
|
2475
2493
|
});
|
|
2476
2494
|
program.command("cancel <type> <id>").option("--env <name>", "environment").description("cancel a run").action(async (type, id, options) => {
|
|
2477
2495
|
const runType = parseRunType(type);
|
|
2478
|
-
|
|
2496
|
+
const config = await resolveConfig(options.env);
|
|
2497
|
+
print(withResolvedTarget(config, await clientFor(config).runs.cancel(runType, id)), program.opts());
|
|
2479
2498
|
});
|
|
2480
2499
|
program.command("action").command("run <ref>").option("--input <json>", "input payload", "{}").option("--space <spaceId>", "target space (defaults to the configured space)").option("--env <name>", "environment").option("--release-id <id>", "pinned release id").option("--manifest-name <name>", "current release selector").description("start an Action Run").action(async (ref, options) => {
|
|
2481
|
-
|
|
2500
|
+
const config = await resolveConfig(options.env, options.space);
|
|
2501
|
+
print(withResolvedTarget(config, await clientFor(config).actions.run(ref, JSON.parse(options.input), {
|
|
2482
2502
|
releaseId: options.releaseId,
|
|
2483
2503
|
manifestName: options.manifestName
|
|
2484
|
-
}), program.opts());
|
|
2504
|
+
})), program.opts());
|
|
2485
2505
|
});
|
|
2486
2506
|
program.command("workflow").command("trigger <ref>").option("--input <json>", "input payload", "{}").option("--space <spaceId>", "target space (defaults to the configured space)").option("--env <name>", "environment").option("--release-id <id>", "pinned release id").option("--manifest-name <name>", "current release selector").description("start a Workflow Run").action(async (ref, options) => {
|
|
2487
|
-
|
|
2507
|
+
const config = await resolveConfig(options.env, options.space);
|
|
2508
|
+
print(withResolvedTarget(config, await clientFor(config).workflows.trigger(ref, JSON.parse(options.input), {
|
|
2488
2509
|
releaseId: options.releaseId,
|
|
2489
2510
|
manifestName: options.manifestName
|
|
2490
|
-
}), program.opts());
|
|
2511
|
+
})), program.opts());
|
|
2491
2512
|
});
|
|
2492
2513
|
program.command("decisions").option("--env <name>", "environment").option("--actionable", "only generations this actor could answer").description("list pending decisions").action(async (options) => {
|
|
2493
2514
|
print(await clientFor(await resolveConfig(options.env)).decisions.list({
|
|
@@ -2496,10 +2517,12 @@ program.command("decisions").option("--env <name>", "environment").option("--act
|
|
|
2496
2517
|
}), program.opts());
|
|
2497
2518
|
});
|
|
2498
2519
|
program.command("approve <id>").option("--env <name>", "environment").option("--reason <reason>", "bounded reason recorded on the response").description("approve a decision").action(async (id, options) => {
|
|
2499
|
-
|
|
2520
|
+
const config = await resolveConfig(options.env);
|
|
2521
|
+
print(withResolvedTarget(config, await clientFor(config).decisions.approve(id, { ...options.reason === void 0 ? {} : { reason: options.reason } })), program.opts());
|
|
2500
2522
|
});
|
|
2501
2523
|
program.command("reject <id>").option("--env <name>", "environment").option("--reason <reason>", "bounded reason recorded on the response").description("reject a decision").action(async (id, options) => {
|
|
2502
|
-
|
|
2524
|
+
const config = await resolveConfig(options.env);
|
|
2525
|
+
print(withResolvedTarget(config, await clientFor(config).decisions.reject(id, { ...options.reason === void 0 ? {} : { reason: options.reason } })), program.opts());
|
|
2503
2526
|
});
|
|
2504
2527
|
program.command("events").option("--follow", "follow runtime events").option("--env <name>", "environment").description("show recent events or follow the event stream").action(async (options) => {
|
|
2505
2528
|
const client = clientFor(await resolveConfig(options.env));
|